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

# Copyright 2012-2016 Mir Calculate. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

from __future__ import print_function
from __future__ import absolute_import
from calculate.consolegui import qt
import urllib.request as urllib2

from .DisplayMethod import DisplayMethod, StartWidget, ConnectLostLabel
from .mainframe import MainFrame
from .mainmenu import MainMenu
from .ControlButton import MethodNameWgt, ControlButtonWgt
from .helpwidget import HelpWgt, BugWgt
from .tools import ToolsWidget

from .conf_connection import FrameConnection
from .LeftMenu import LeftMenu
from .MainFrameResult import MainFrameRes
from .View_Process import ViewProc
from .session_function import ViewSessionInfo
from .CertificateClass import CertClass

from .pid_information import client_list_pid
from .more import icon_visible, client_del_sid, show_msg, get_icon

DEBUG_LEVEL = 0


def debug(level, *args):
    if level <= DEBUG_LEVEL:
        for s in args:
            print(s, end=' ')
        print()

class MainWgt(qt.QMainWindow):
    def __init__(self, ClientObj):
        super().__init__()
        self.ClientObj = ClientObj
        self.initUI()

    def initUI(self):
        # Create bottom status bar
        #        self.statusbar = self.statusBar()

        self.Main = qt.QWidget(self)

        self.vlayout = qt.QVBoxLayout(self.Main)

        # Create top main menu
        self.topmenu = MainMenu(self)
        self.vlayout.addWidget(self.topmenu)

        self.layout_wgt = qt.QWidget(self)
        self.layout = qt.QGridLayout(self.layout_wgt)
        self.layout.setAlignment(qt.Qt.AlignLeft)

        # add control button widget
        self.methodname_wgt = MethodNameWgt(self, self.ClientObj)
        self.control_button = ControlButtonWgt(self, self.ClientObj)

        self.layout.addWidget(self.methodname_wgt, 0, 0, 1, 2)

        self.left_frame = LeftMenu(self, self.ClientObj)
        self.left_frame.hide()

        # Main Frame
        self.main_frame = qt.QScrollArea(self)
        self.main_frame.setFrameShape(qt.QFrame.NoFrame)
        self.main_frame.setObjectName('MF')
        #self.main_frame.setStyleSheet("#MF " "{background-color: #FFFFFF;}")

        self.MainFrameWgt = StartWidget(self)
        self.main_frame.setWidget(self.MainFrameWgt)
        self.main_frame.setWidgetResizable(True)

        self.layout.addWidget(self.left_frame, 1, 0, 2, 1)
        self.layout.addWidget(self.main_frame, 1, 1)
        self.layout.addWidget(self.control_button, 2, 1)

        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)

        self.vlayout.addWidget(self.layout_wgt)
        self.vlayout.setContentsMargins(0, 0, 0, 0)
        self.vlayout.setSpacing(0)

        self.setCentralWidget(self.Main)

    def updateColors(self):
        self.MainFrameWgt.updateColors()

    def onChanged(self, text):
        self.lbl.setText(text)
        self.lbl.adjustSize()

    def connecting(self):
        self.cur_size = self.size()
        self.ConnectWidget = FrameConnection(self, self.ClientObj)
        self.ConnectWidget.setWindowModality(qt.Qt.WindowModal)
        self.ConnectWidget.initUI(self, self.ClientObj._parent)
        self.ConnectWidget.show()

    def connect_to_localhost(self, host=None, port=None):
        self.cur_size = self.size()
        self.ConnectWidget = FrameConnection(self, self.ClientObj)
        if not host:
            host = 'localhost'
        self.ConnectWidget.connect_to_host(host, port, auto=True)

    # 3 methods for help menu
    def help(self):
        self.HelpWidget = HelpWgt(self)
        self.HelpWidget.setWindowModality(qt.Qt.WindowModal)
        self.HelpWidget.show()

    def hand_book(self):
        if self.ClientObj.lang == 'ru':
            site = "http://www.calculate-linux.ru/main/ru/calculate-console-gui"
        else:
            site = "http://www.calculate-linux.org/main/en/calculate-console-gui"
        qt.QDesktopServices.openUrl(qt.QUrl(site))

    def bug_report(self):
        self.bugWidget = BugWgt(self)
        self.bugWidget.setWindowModality(qt.Qt.WindowModal)
        self.bugWidget.show()

    def tools(self):
        self.ToolsWgt = ToolsWidget(self, self.ClientObj,
                                    self.ClientObj._parent)
        self.ToolsWgt.show()

    def work_with_certificates(self):
        self.certWidget = CertClass(self, self.ClientObj, \
                                    self.ClientObj._parent)
        self.certWidget.show()

    def display_methods(self):
        self.delete_MainFrameWgt()

        self.MainFrameWgt = DisplayMethod(self, self.ClientObj)
        self.MainFrameWgt.refresh()
        self.main_frame.setWidget(self.MainFrameWgt)
        self.main_frame.setWidgetResizable(True)

        self.left_frame.hide()
        self.left_frame.old_title = None

        #        icon_visible(self, 'Methods', False)
        icon_visible(self, 'Back', False)
        self.resize(self.cur_size)

    def back(self):
        # self.control_button.del_button()
        if len(self.ClientObj.back_step_list) < 2:
            self.delete_MainFrameWgt()

            self.MainFrameWgt = DisplayMethod(self, self.ClientObj)
            self.MainFrameWgt.refresh()
            self.main_frame.setWidget(self.MainFrameWgt)
            self.main_frame.setWidgetResizable(True)

            self.left_frame.hide()
            self.left_frame.old_title = None

            #            icon_visible(self, 'Methods', False)
            icon_visible(self, 'Back', False)

        else:
            # get WindowTitle and delete last item from back_step_list
            title = self.ClientObj.back_step_list.pop()[2]
            # get group, subgroup
            group, subgroup, temp = self.ClientObj.back_step_list \
                [len(self.ClientObj.back_step_list) - 1]

            # create new group in left menu
            self.left_frame.groupActivated(group, subgroup, title, \
                                           self.ClientObj, True)

    def view_processes(self):
        self.delete_MainFrameWgt()
        self.MainFrameWgt = ViewProc(self, self.ClientObj)
        self.main_frame.setWidget(self.MainFrameWgt)
        self.main_frame.setWidgetResizable(True)

        self.left_frame.hide()

        #        icon_visible(self, 'Methods', True)
        icon_visible(self, 'Back', True)

    def view_session_info(self):
        self.SessionWgt = ViewSessionInfo(self, self.ClientObj.client, \
                                          self.ClientObj._parent)
        self.SessionWgt.setWindowModality(qt.Qt.WindowModal)
        self.SessionWgt.show()

    def disconnect(self, new_session=False):
        if not self.ClientObj.client:
            return 1

        if new_session:
            reply = qt.QMessageBox.Yes
        else:
            reply = self.show_close_messagebox()

        if reply in [qt.QMessageBox.No, qt.QMessageBox.Yes]:
            if hasattr(self.ClientObj, 'signaling'):
                if self.ClientObj.signaling.isRunning():
                    self.ClientObj.signaling.close()
                    self.ClientObj.signaling.wait()

        if reply == qt.QMessageBox.Yes:
            # Exit with closing session
            client_del_sid(self.ClientObj.client)
            self.ClientObj.param_objects = {}

        if reply in [qt.QMessageBox.No, qt.QMessageBox.Yes]:
            if not self.topmenu.Processes.isEnabled():
                self.topmenu.Processes.setEnabled(True)
                self.topmenu.Session.setEnabled(True)
                self.topmenu.Back.setEnabled(True)
            if hasattr(self, 'con_lost_lbl'):
                self.con_lost_lbl.hide()
                self.con_lost_lbl.close()

            if hasattr(self.ClientObj._parent, 'set_localhost'):
                if self.ClientObj.client.server_host_name in \
                        ['127.0.0.1', 'localhost']:
                    self.ClientObj._parent.set_localhost(None)
            else:
                self.ClientObj._parent.connect()
                return 0
            self.ClientObj.client = None
            self.ClientObj._parent.connect_count_changed(
                self.ClientObj.host_name, self.ClientObj.port, 0)
            #            icon_visible(self, 'Methods', False)
            icon_visible(self, 'Back', False)
            icon_visible(self, 'Disconnect', False)
            icon_visible(self, 'Processes', False)
            icon_visible(self, 'Session', False)
            icon_visible(self, 'Connect', True)
            icon_visible(self, 'Certificates', True)
            self.process_dict = {}

            if hasattr(self.ClientObj._parent, 'rename_tab'):
                self.ClientObj._parent.rename_tab()
        else:
            return 0

        self.delete_MainFrameWgt()
        self.MainFrameWgt = StartWidget(self)
        self.main_frame.setWidget(self.MainFrameWgt)
        self.main_frame.setWidgetResizable(True)

        self.left_frame.hide()

        # set new Title
        self.ClientObj._parent.setWindowTitle(self.ClientObj.Name)
        return 0

    def reconnect_to_host(self):
        self.ClientObj.app.processEvents()
        server_host_name = self.ClientObj.client.server_host_name
        password = self.ClientObj.client.password
        self.disconnect(True)

        if hasattr(self.ClientObj._parent, 'set_localhost'):
            # Reconnet to current host
            self.cur_size = self.size()
            self.ConnectWidget = FrameConnection(self, self.ClientObj)
            self.ConnectWidget.connect_to_host(server_host_name,
                                               self.ClientObj.port,
                                               re_passwd=password)

            if not self.main_frame.isEnabled():
                self.left_frame.setEnabled(True)
                self.main_frame.setEnabled(True)
                self.control_button.setEnabled(True)

    def main_frame_view(self, view, method_name, step_change=False, \
                        change_offset=False, error_output=True,
                        skip_options=False, new_step=None):
        if change_offset:
            self.MainFrameWgt = MainFrame(self, self.ClientObj, view, \
                                          method_name, error_output)
            self.MainFrameWgt.initUI(True)
            return
        self.delete_MainFrameWgt()
        self.MainFrameWgt = MainFrame(self, self.ClientObj, view, method_name, \
                                      error_output, skip_options=skip_options)
        self.MainFrameWgt.initUI()
        if new_step:
            self.MainFrameWgt.refresh_view(int(new_step))
        self.main_frame.setWidget(self.MainFrameWgt)
        self.main_frame.setWidgetResizable(True)

    def main_frame_res(self, method_name, meth_result, change_offset=False):
        if change_offset:
            TempMainFrameWgt = MainFrameRes(self, self.ClientObj, method_name,
                                            meth_result, change_offset)
            self.left_frame.hide()

            try:
                TempMainFrameWgt.analysis(meth_result)
            except (RuntimeError, ValueError):
                pass
            except urllib2.URLError as e:
                show_msg(e, 'URLError')

        else:
            self.delete_MainFrameWgt()
            self.MainFrameWgt = MainFrameRes(self, self.ClientObj,
                                             method_name, meth_result)
            self.main_frame.setWidget(self.MainFrameWgt)
            self.main_frame.setWidgetResizable(True)

            self.left_frame.hide()

            try:
                self.MainFrameWgt.analysis(meth_result)
            except (RuntimeError, ValueError):
                pass
            except urllib2.URLError as e:
                show_msg(e, 'URLError')

    def main_view_process(self, method_name, meth_result, pid):
        self.delete_MainFrameWgt()
        self.MainFrameWgt = MainFrameRes(self, self.ClientObj,
                                         method_name, meth_result)
        self.main_frame.setWidget(self.MainFrameWgt)
        self.main_frame.setWidgetResizable(True)

        self.left_frame.hide()

        #DEBUG

        #check why are they here?
        # try:
        self.MainFrameWgt.get_entire_frame(pid)
        # except (RuntimeError, ValueError):
        #     pass

    def delete_MainFrameWgt(self):
        self.main_frame.takeWidget()
        # try:
        self.MainFrameWgt.close()
        # except (RuntimeError, AttributeError):
        #     pass

    def setScrollBarVal(self):
        self.main_frame.verticalScrollBar().setSliderPosition \
            (self.main_frame.verticalScrollBar().maximum())

    def signaling_slot(self, sid, reply):
        if reply == 2:
            # Create ConnectLostLabel
            if hasattr(self, 'con_lost_lbl'):
                self.con_lost_lbl.hide()
                self.con_lost_lbl.close()
            self.con_lost_lbl = ConnectLostLabel(_('Connection lost!'), self)
            host_name = self.ClientObj.client.server_host_name
            port = self.ClientObj.port
            if host_name in ('127.0.0.1', 'localhost'):
                try:
                    from calculate.lib.utils.dbus_tools import run_dbus_core
                    run_dbus_core(host_name, port)
                except ImportError:
                    pass
                
            self.topmenu.Processes.setDisabled(True)
            self.topmenu.Session.setDisabled(True)
            self.topmenu.Back.setDisabled(True)
            self.con_lost_lbl.show()
        elif reply == 0:
            if hasattr(self, 'con_lost_lbl'):
                self.con_lost_lbl.hide()
                self.con_lost_lbl.close()
            if not self.main_frame.isEnabled():
                self.left_frame.setEnabled(True)
                self.main_frame.setEnabled(True)
                self.control_button.setEnabled(True)
                self.topmenu.Processes.setEnabled(True)
                self.topmenu.Session.setEnabled(True)
                self.topmenu.Back.setEnabled(True)
                if hasattr(self.MainFrameWgt, 'button_enabled'):
                    self.MainFrameWgt.button_enabled()
        else:
            if hasattr(self, 'con_lost_lbl'):
                self.con_lost_lbl.hide()
                self.con_lost_lbl.close()
            self.con_lost_lbl = ConnectLostLabel(
                _("The server was restarted") + '.\n' + \
                _('Reconnecting to the server') + '...',
                self)
            self.topmenu.Processes.setDisabled(True)
            self.topmenu.Session.setDisabled(True)
            self.topmenu.Back.setDisabled(True)
            self.con_lost_lbl.show()
            self.reconnect_to_host()

    def resizeEvent(self, event):
        if hasattr(self, 'con_lost_lbl'):
            if self.con_lost_lbl.isVisible():
                self.con_lost_lbl.resize_widget()
        event.accept()

    def show_close_messagebox(self):
        list_pid = client_list_pid(self.ClientObj.client)

        if not list_pid:
            return qt.QMessageBox.Yes

        msgBox = qt.QMessageBox(self)
        msgBox.setWindowTitle(_('Closing session'))
        msgBox.setText(_("Close this session") + ' ' + _('with %s?') \
                       % self.ClientObj.host_name + '\t')
        if len(list_pid):
            if str(len(list_pid)).endswith('1'):
                msgBox.setInformativeText(_('Once the session is closed, ' \
                                            'data on process %d will be lost!') % len(
                    list_pid))
            if len(list_pid) > 1:
                msgBox.setInformativeText(_('Once the session is closed, ' \
                                            'data on process %d will be lost!') % len(
                    list_pid))

        msgBox.setStandardButtons(qt.QMessageBox.Yes | qt.QMessageBox.No | \
                                  qt.QMessageBox.Cancel)

        # translate
        msgBox.button(msgBox.Yes).setText(_('Yes'))
        msgBox.button(msgBox.No).setText(_('No'))
        msgBox.button(msgBox.Cancel).setText(_('Cancel'))

        msgBox.setDefaultButton(qt.QMessageBox.Cancel)
        msgBox.setWindowIcon(get_icon("application-exit"))
        reply = msgBox.exec_()
        return reply

    def _closeEvent(self):
        if self.ClientObj.client:
            reply = self.show_close_messagebox()

            if reply == qt.QMessageBox.Yes or reply == qt.QMessageBox.No:
                self.topmenu.Processes.setEnabled(True)
                self.topmenu.Session.setEnabled(True)
                self.topmenu.Back.setEnabled(True)
                if hasattr(self, 'con_lost_lbl'):
                    self.con_lost_lbl.hide()
                    self.con_lost_lbl.close()
                # Exit with closing session
                if hasattr(self.ClientObj, 'signaling'):
                    if self.ClientObj.signaling.isRunning():
                        self.ClientObj.signaling.close()
                        self.ClientObj.signaling.wait()

                if hasattr(self.ClientObj._parent, 'set_localhost'):
                    if self.ClientObj.client.server_host_name in \
                            ['127.0.0.1', 'localhost']:
                        self.ClientObj._parent.set_localhost(None)

                if reply == qt.QMessageBox.Yes:
                    # Closing session
                    client_del_sid(self.ClientObj.client)
                return 1
            else:
                return 0
        else:
            return 1

    def keyPressEvent(self, e):
        if e.key() == qt.Qt.Key_Return:
            self.control_button.keyPressEvent(e)
        else:
            qt.QMainWindow.keyPressEvent(self, e)
