# -*- coding: utf-8 -*-

"""
The output tab for the main toolbar

@author: Chris Scott

"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import shutil
import subprocess
import copy
import logging
import math
import functools
import datetime
import time

import numpy as np
from PySide2 import QtGui, QtCore, QtWidgets

from PIL import Image

from ..visutils import utilities
from ..visutils import threading_vis
from ..visutils.utilities import iconPath
from . import genericForm
from ..plotting import rdf
from ..algebra import _vectors as vectors_c
from ..plotting import plotDialog
from . import utils
import six
from six.moves import range


class OutputDialog(QtWidgets.QDialog):
    def __init__(self, parent, mainWindow, width, index):
        super(OutputDialog, self).__init__(parent)

        self.parent = parent
        self.rendererWindow = parent
        self.mainToolbar = parent
        self.mainWindow = mainWindow
        self.width = width

        self.setWindowTitle("Output - Render window %d" % index)
        self.setModal(0)

        # size
        self.resize(QtCore.QSize(350, 600))

        # layout
        outputTabLayout = QtWidgets.QVBoxLayout(self)
        outputTabLayout.setContentsMargins(0, 0, 0, 0)
        outputTabLayout.setSpacing(0)
        outputTabLayout.setAlignment(QtCore.Qt.AlignTop)

        # add tab bar
        self.outputTypeTabBar = QtWidgets.QTabWidget(self)
        self.outputTypeTabBar.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)

        # add tabs to tab bar

        # image tab
        imageTabWidget = QtWidgets.QWidget()
        imageTabLayout = QtWidgets.QVBoxLayout(imageTabWidget)
        imageTabLayout.setContentsMargins(0, 0, 0, 0)

        self.imageTab = ImageTab(self, self.mainWindow, self.width)
        imageTabLayout.addWidget(self.imageTab)

        self.outputTypeTabBar.addTab(imageTabWidget, "Image")

        # file tab
        fileTabWidget = QtWidgets.QWidget()
        fileTabLayout = QtWidgets.QVBoxLayout(fileTabWidget)
        fileTabLayout.setContentsMargins(0, 0, 0, 0)

        self.fileTab = FileTab(self, self.mainWindow, self.width)
        fileTabLayout.addWidget(self.fileTab)
        self.outputTypeTabBar.addTab(fileTabWidget, "File")

        # plot tab
        self.plotTab = PlotTab(self.mainWindow, self.rendererWindow, parent=self)
        self.outputTypeTabBar.addTab(self.plotTab, "Plot")

        # add tab bar to layout
        outputTabLayout.addWidget(self.outputTypeTabBar)


class ScalarsHistogramOptionsForm(genericForm.GenericForm):
    """
    Main options form for scalars histograms

    """
    def __init__(self, parent, mainWindow, rendererWindow):
        super(ScalarsHistogramOptionsForm, self).__init__(parent, 0, "Histogram plot options")

        self.mainWindow = mainWindow
        self.rendererWindow = rendererWindow

        # current number of scalar plots
        self.numScalarsPlots = 0

        # current plots
        self.currentPlots = {}

        # add combo box
        self.scalarsCombo = QtWidgets.QComboBox()
        self.scalarsCombo.currentIndexChanged[int].connect(self.scalarsComboChanged)
        self.newRow().addWidget(self.scalarsCombo)

        # add stacked widget
        self.stackedWidget = QtWidgets.QStackedWidget()
        self.newRow().addWidget(self.stackedWidget)

        self.logger = logging.getLogger(__name__ + ".ScalarsHistogramOptionsForm")

    def scalarsComboChanged(self, index):
        """
        Scalars combo changed

        """
        self.stackedWidget.setCurrentIndex(index)

    def removeScalarPlotOptions(self):
        """
        Remove scalar plot options

        """
        self.logger.debug("Removing scalar plot options")
        for scalarsID in list(self.currentPlots.keys()):
            self.logger.debug(" Removing: '%s'", scalarsID)
            form = self.currentPlots.pop(scalarsID)
            self.stackedWidget.removeWidget(form)
            form.deleteLater()
            self.scalarsCombo.removeItem(0)

        self.numScalarsPlots = 0

    def addAtomPropertyPlotOptions(self):
        """
        Add atom property plot options

        """
        self.logger.debug("Adding atom property plot options")

        # get current pipeline page
        pp = self.rendererWindow.getCurrentPipelinePage()
        ppindex = pp.pipelineIndex
        lattice = pp.inputState

        # add charge plot option
        scalarsArray = lattice.charge
        if np.min(scalarsArray) == 0 == np.max(scalarsArray):
            self.logger.debug(" Skipping charge: all zero")
        else:
            self.logger.debug(" Adding charge plot")
            scalarsName = "Charge"
            scalarsID = "%s (%d)" % (scalarsName, ppindex)
            self.addScalarPlotOptions(scalarsID, scalarsName, scalarsArray)

    def addScalarPlotOptions(self, scalarsID, scalarsName, scalarsArray):
        """
        Add plot for scalar 'name'

        """
        # don't add duplicates (should never happen anyway)
        if scalarsID in self.currentPlots:
            return

        # don't add empty arrays
        if not len(scalarsArray):
            return

        self.logger.debug("Adding scalar plot option: '%s'", scalarsID)

        # create form
        form = GenericHistogramPlotForm(self, scalarsID, scalarsName, scalarsArray)

        # add to stacked widget
        self.stackedWidget.addWidget(form)

        # add to combo box
        self.scalarsCombo.addItem(scalarsID)

        # store in dict
        self.currentPlots[scalarsID] = form

        # number of plots
        self.numScalarsPlots += 1

    def refreshScalarPlotOptions(self):
        """
        Refresh plot options

        * Called after pipeline page has run filters/single filter has run
        * loops over all filter lists under pipeline page, adding plots for all scalars
        * plots named after pipeline index and filter list index
        * also called when renderWindow pipeline index changes
        * also called when filter lists are cleared, etc...?

        """
        self.logger.debug("Refreshing plot options")

        # remove old options
        self.removeScalarPlotOptions()

        # get current pipeline page
        pp = self.rendererWindow.getCurrentPipelinePage()
        ppindex = pp.pipelineIndex

        # get filter lists
        filterLists = pp.filterLists

        # first add atom properties (KE, PE, charge)
        self.addAtomPropertyPlotOptions()

        # loop over filter lists, adding scal
ars
        self.logger.debug("Looping over filter lists (%d)", len(filterLists))
        for filterList in filterLists:
            # make unique name for pipeline page/filter list combo
            findex = filterList.tab
            filterListID = "%d-%d" % (ppindex, findex)
            
self.logger.debug("Filter list %d; id '%s'", filterList.tab, filterListID)

            # loop over scalars in scalarsDict on filterer
            for scalarsName, scalarsArray in six.iteritems(filterList.filterer.scalarsDict):
                # make unique id
                scalarsID = "%s (%s)" % (scalarsName, filterListID)

                # add
                self.addScalarPlotOptions(scalarsID, scalarsName, scalarsArray)

            # loop over scalars in latticeScalarsDict on filterer
            latticeScalarKeys = list(filterList.pipelinePage.inputState.scalarsDict.keys())
            for key in latticeScalarKeys:
                if key in filterList.filterer.latticeScalarsDict:
                    scalarsArray = filterList.filterer.latticeScalarsDict[key]
                    self.logger.debug("Using Filterer scalars for '%s'", key)

                else:
                    scalarsArray = filterList.pipelinePage.inputState.scalarsDict[key]
                    self.logger.debug("Using Lattice scalars for '%s'", key)

                # make unique id
                scalarsName = key
                scalarsID = "%s (%s)" % (scalarsName, filterListID)

                # add
                self.addScalarPlotOptions(scalarsID, sca