# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import sys

from pathlib import Path

from PySide6.QtCore import QFile, QIODevice, QObject
from PySide6.QtDataVisualization import (QBar3DSeries, QCategory3DAxis, QValue3DAxis)

from variantbardataproxy import VariantBarDataProxy
from variantbardatamapping import VariantBarDataMapping
from variantdataset import VariantDataSet


MONTHS = ["January", "February", "March", "April",
          "May", "June", "July", "August", "September", "October",
          "November", "December"]


class RainfallData(QObject):

    def __init__(self):
        super().__init__()
        self._columnCount = 0
        self._rowCount = 0
        self._years = []
        self._numericMonths = []
        self._proxy = VariantBarDataProxy()
        self._mapping = None
        self._dataSet = None
        self._series = QBar3DSeries()
        self._valueAxis = QValue3DAxis()
        self._rowAxis = QCategory3DAxis()
        self._colAxis = QCategory3DAxis()

        # In data file the months are in numeric format, so create custom list
        for i in range(1, 13):
            self._numericMonths.append(str(i))

        self._columnCount = len(self._numericMonths)

        self.updateYearsList(2010, 2022)

        # Create proxy and series
        self._proxy = VariantBarDataProxy()
        self._series = QBar3DSeries(self._proxy)

        self._series.setItemLabelFormat("%.1f mm")

        # Create the axes
        self._rowAxis = QCategory3DAxis(self)
        self._colAxis = QCategory3DAxis(self)
        self._valueAxis = QValue3DAxis(self)
        self._rowAxis.setAutoAdjustRange(True)
        self._colAxis.setAutoAdjustRange(True)
        self._valueAxis.setAutoAdjustRange(True)

        # Set axis labels and titles
        self._rowAxis.setTitle("Year")
        self._colAxis.setTitle("Month")
        self._valueAxis.setTitle("rainfall (mm)")
        self._valueAxis.setSegmentCount(5)
        self._rowAxis.setLabels(self._years)
        self._colAxis.setLabels(MONTHS)
        self._rowAxis.setTitleVisible(True)
        self._colAxis.setTitleVisible(True)
        self._valueAxis.setTitleVisible(True)

        self.addDataSet()

    def customSeries(self):
        return self._series

    def valueAxis(self):
        return self._valueAxis

    def rowAxis(self):
        return self._rowAxis

    def colAxis(self):
        return self._colAxis

    def updateYearsList(self, start, end):
        self._years.clear()
        for i in range(start, end + 1):
            self._years.append(str(i))
        self._rowCount = len(self._years)

    def addDataSet(self):
        # Create a new variant data set and data item list
        self._dataSet = VariantDataSet()
        itemList = []

        # Read data from a data file into the data item list
        file_path = Path(__file__).resolve().parent / "data" / "raindata.txt"
        dataFile = QFile(file_path)
        if dataFile.open(QIODevice.ReadOnly | QIODevice.Text):
            data = dataFile.readAll().data().decode("utf8")
            for line in data.split("\n"):
                if line and not line.startswith("#"):  # Ignore comments
                    tokens = line.split(",")
                    # Each line has three data items: Year, month, and
                    # rainfall value
                    if len(tokens) >= 3:
                        # Store year and month as strings, and rainfall value
                        # as double into a variant data item and add the item to
                        # the item list.
                        newItem = []
                        newItem.append(tokens[0].strip())
                        newItem.append(tokens[1].strip())
                        newItem.append(float(tokens[2].strip()))
                        itemList.append(newItem)
        else:
            print("Unable to open data file:", dataFile.fileName(),
                  file=sys.stderr)

        # Add items to the data set and set it to the proxy
        self._dataSet.addItems(itemList)
        self._proxy.setDataSet(self._dataSet)

        # Create new mapping for the data and set it to the proxy
        self._mapping = VariantBarDataMapping(0, 1, 2,
                                              self._years, self._numericMonths)
        self._proxy.setMapping(self._mapping)
