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

import os
from queue import Queue

from PyQt5 import QtGui
from PyQt5.QtCore import (
    QTranslator, QEvent
)
from PyQt5.QtWidgets import (
    QMainWindow, QApplication, QAction,
    QFileDialog,
)
from PyQt5.uic import loadUi

from View.ASubWindow import WindowToolKit
from View.ListedSubWindow import ListedSubWindow
from View.DummyWindow import DummyWindow

from View.Configure.Window import ConfigureWindow
from View.Study.Window import NewStudyWindow
from View.About.Window import AboutWindow
from View.Network.Window import NetworkWindow
from View.Geometry.Window import GeometryWindow
from View.BoundaryCondition.Window import BoundaryConditionWindow
from View.LateralContribution.Window import LateralContributionWindow
from View.Stricklers.Window import StricklersWindow
from View.Sections.Window import SectionsWindow

from Model.Study import Study

no_model_action = [
    "action_menu_new", "action_menu_open", "action_menu_import_mage",
    "action_menu_import_rubarbe", "action_toolBar_open",
]

model_action = [
    "action_menu_close", "action_menu_edit", "action_menu_save",
    "action_menu_save_as", "action_toolBar_close", "action_toolBar_save",
]

other_model_action = [
    "action_toolBar_run_solver", "action_toolBar_kill_solver"
]

define_model_action = [
    "action_toolBar_network", "action_toolBar_geometry",
    "action_toolBar_mesh", "action_toolBar_run_meshing_tool",
    "action_toolBar_boundary_cond", "action_toolBar_lateral_contrib",
    "action_toolBar_spills", "action_toolBar_sections",
    "action_toolBar_stricklers", "action_toolBar_building",
]

action = (
    no_model_action + model_action + define_model_action
)

class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
    def __init__(self, conf=None):
        super(ApplicationWindow, self).__init__()

        # App Configuration
        self.conf = conf

        # Model
        self.model = None

        # UI
        self.ui = loadUi(
            os.path.join(os.path.dirname(__file__), "ui", "MainWindow.ui"),
            self
        )

        self.init_callback()
        self.default_style()

        self.trans = QTranslator(self)
        #self.ui.retranslateUi()

    def set_title(self):
        if self.model is not None:
            self.setWindowTitle(f"PAMHYR - {self.model.name}")
        else:
            self.setWindowTitle("PAMHYR")

    def enable_actions(self, action:str, enable:bool):
        """Enable of disable an action componant

        Args:
            action: Action to enable/disable
            enable: True to Enable, or False to disable

        Returns:
            Nothing
        """
        self.findChild(QAction, action).setEnabled(enable)

    def init_callback(self):
        """Connect action to callback function

        Returns:
            Nothing
        """
        actions = {
            # Menu action
            "action_menu_config": self.open_configure,
            "action_menu_new": self.open_new_study,
            "action_menu_edit": self.open_edit_study,
            "action_menu_open": self.open_model,
            "action_menu_save": self.save_study,
            "action_menu_save_as": self.save_as_study,
            ## Help
            "action_menu_about": self.open_about,
            # ToolBar action
            "action_toolBar_quit": self.close,
            "action_toolBar_open": self.open_model,
            "action_toolBar_save": self.save_study,
            "action_toolBar_close": self.close_model,
            "action_toolBar_run_solver": self.open_dummy,
            "action_toolBar_kill_solver": self.open_dummy,
            "action_toolBar_listing": self.open_dummy,
            ## Current actions
            "action_toolBar_network": self.open_network,
            "action_toolBar_geometry": self.open_geometry,
            "action_toolBar_mesh": lambda: self.open_dummy("Mesh"),
            "action_toolBar_run_meshing_tool": lambda: self.open_dummy("Lancement mailleur externe"),
            "action_toolBar_boundary_cond": self.open_boundary_cond,
            "action_toolBar_lateral_contrib": self.open_lateral_contrib,
            "action_toolBar_spills": lambda: self.open_dummy("Deversement"),
            "action_toolBar_stricklers": self.open_stricklers,
            "action_toolBar_sections": self.open_sections,
            "action_toolBar_building": lambda: self.open_dummy("Ouvrages"),
        }

        for action in actions:
            self.findChild(QAction, action)\
                .triggered.connect(actions[action])
            # action.triggered.connect(actions[action])


    def changeEvent(self, event):
        if event.type() == QEvent.LanguageChange:
            self.retranslateUi()
        super(ApplicationWindow, self).changeEvent(event)

    def default_style(self):
        """Set default window style

        Returns:
            Nothing
        """
        self.update_enable_action()
        # Maximise window
        self.showMaximized()

    #########
    # MODEL #
    #########

    def get_model(self):
        return self.model

    def set_model(self, model):
        self.model = model
        self.update_enable_action()
        self.set_title()

    def close_model(self):
        self.model = None
        self.update_enable_action()
        self.set_title()

    def update_enable_action(self):
        """Update status of action componante

        Update status of action componant, enable or disable in
        function of model state

        Returns:
            Nothing
        """
        no_model = self.model is None

        for action in no_model_action:
            self.enable_actions(action, no_model)

        for action in define_model_action + other_model_action:
            self.enable_actions(action, not no_model)

        for action in model_action:
            self.enable_actions(action, not no_model)

    ############
    # FEATURES #
    ############

    def save_study(self):
        """Save current study

        Save current study, if study as no associate file, open a
        file dialog.

        Returns:
            Nothing
        """
        if self.model.filename == "":
            file_name, _ = QFileDialog.getSaveFileName(
                self, "Save File",
                "", "Pamhyr(*.pkl)"
            )

            if file_name[-4:] == ".pkl":
                self.model.filename = file_name
            else:
                self.model.filename = file_name + ".pkl"

        self.model.save()

    def save_as_study(self):
        """Save current study as new file

        Save current study as new file, if study as no associate file,
        open a file dialog.

        Returns:
            Nothing
        """
        file_name, _ = QFileDialog.getSaveFileName(
            self, "Save File",
            "", "Pamhyr(*.pkl)"
        )

        if file_name[-4:] == ".pkl":
            self.model.filename = file_name
        else:
            self.model.filename = file_name + ".pkl"

        self.model.save()

    #############
    # SUBWINDOW #
    #############

    def open_configure(self):
        """Open configure window

        Open PamHyr configure window

        Returns:
            Nothing
        """
        self.config = ConfigureWindow(conf=self.conf, parent=self)
        self.config.show()

    def open_about(self):
        """Open about window

        Open a new window with information about PamHyr

        Returns:
            Nothing
        """
        self.about = AboutWindow(parent=self)
        self.about.show()

    def open_model(self):
        """Open file dialog to select saved model

        Returns:
            Nothing
        """
        if self.model is None:
            dialog = QFileDialog(self)
            dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
            dialog.setDefaultSuffix(".pkl")
            #dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden)
            dialog.setNameFilters(['PamHyr (*.pkl)'])

            if dialog.exec_():
                file_name = dialog.selectedFiles()
                self.set_model(Study.open(file_name[0]))
                print(f"[MainWindow] Open Study : {self.model.name}")

    def open_new_study(self):
        """Open dialog to set new study

        Returns:
            Nothing
        """
        if self.model is None:
            self.new_study = NewStudyWindow(parent=self)
            self.new_study.show()

    def open_edit_study(self):
        """Open dialog to set new study

        Returns:
            Nothing
        """
        if not self.model is None:
            self.new_study = NewStudyWindow(study=self.model, parent=self)
            self.new_study.show()

    def open_network(self):
        """Open network dialog

        Returns:
            Nothing
        """
        if (self.model is not None and
            not self.sub_win_exists("River network")):
            self.network = NetworkWindow(model=self.model, parent=self)
            self.network.show()

    def open_geometry(self):
        """Open geometry window

        Returns:
            Nothing
        """
        if (self.model is not None and
            self.model.river.has_current_reach()):
            geometry = GeometryWindow(model=self.model, parent=self)
            geometry.show()
        else:
            self.message_box("Please select a reach",
                             "Geometry edition need a reach selected "
                             "into river network window to work on it")

    def open_boundary_cond(self):
        self.bound = BoundaryConditionWindow(study = self.model, parent=self)
        self.bound.show()

    def open_lateral_contrib(self):
        self.lateral = LateralContributionWindow(study = self.model, parent=self)
        self.lateral.show()

    def open_stricklers(self):
        self.strick = StricklersWindow(
            study = self.model,
            config = self.conf,
            parent=self
        )
        self.strick.show()

    def open_sections(self):
        self.sections = SectionsWindow(
            study = self.model,
            parent=self
        )
        self.sections.show()

    # TODO: Delete me !
    ###############
    # DUMMY STUFF #
    ###############

    def open_dummy(self, title="Dummy"):
        self.dummy = DummyWindow(
            title=title if type(title) is str else "Dummy",
            parent=self
        )
        self.dummy.show()