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

# Copyright 2010-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
import dbus
import dbus.service
import dbus.mainloop.glib

from calculate.consolegui import qt
import time, sys
import calculate.contrib
from suds import MethodNotFound
import os, pwd, shutil
# import ConfigParser
import calculate.lib.configparser as ConfigParser


from .TrayIcon import TrayIcon

from .more import get_sid, get_view_params, _print, get_icon, get_system_rgb, \
    dpivalue
    
from .MainClass import ApiClient
from calculate.consolegui.datavars import DataVarsGui
from .pid_information import client_pid_info
#from calculate.lib.cl_lang import setLocalTranslate
#setLocalTranslate('console_gui',sys.modules[__name__])
import gettext
_ = gettext.gettext
class SelectedMethodWgt(qt.QWidget):
    def __init__(self, app, args):
        super().__init__()
        self.args = args
        self.user_changed_flag = False
        self.lang = args.lang
        self.method = args.method
        self.skip_options = args.skip_options

        # Initialization GUI variables
        self.VarsGui = DataVarsGui()
        self.VarsGui.importGui()
        self.VarsGui.flIniFile()

        self.ClientObj = ApiClient(app, self)
        self.port = args.port or self.VarsGui.GetInteger('core.cl_core_port')
        self.MethodWidget = self.ClientObj.MainWidget
        self.MethodWidget.topmenu.hide()
        layout = qt.QHBoxLayout(self)
        layout.setContentsMargins(0,0,0,0)
        layout.setSpacing(0)
        layout.addWidget(self.MethodWidget)

        icon = get_icon('console-gui-%s'%self.method.replace("_","-"),
                        'calculate-%s'%self.method.replace("_","-"))

        self.setWindowIcon(icon)
        qt.QApplication.setWindowIcon(icon)

        conf_path = self.VarsGui.Get('cl_gui_config_path')
        homePath = self.VarsGui.Get('ur_home_path')
        self.user_config = conf_path.replace("~",homePath)

        if self.connect():
            sys.exit(1)

        if not self.get_size():
            # definition of screen resolution
            prim_screen = app.desktop().primaryScreen()
            d_size = app.desktop().screenGeometry(prim_screen).size()

            # resize main widget
            if d_size.height() < 768:
                self.resize(900,560)
            else:
                self.resize(900, 726)
        self.setMinimumHeight(100)
        self.setMinimumWidth(500)
        self.show()

    def connect(self):
        self.MethodWidget.connect_to_localhost(self.args.host, self.port)
        if not self.ClientObj.client:
            return 1
        self.ClientObj.sid = get_sid(self.ClientObj.client)
        try:
            view_params = get_view_params(self.ClientObj.client, \
                                     self.args.method + '_view', step = 0)
            view = self.ClientObj.client.service[0][self.args.method + \
                                '_view'](int(self.ClientObj.sid), view_params)
        except MethodNotFound:
            _print('Method not found: ', self.args.method + '_view')
            self.close()
            sys.exit(1)
        if self.args.method in self.ClientObj.method_names:
            view_method = self.ClientObj.method_names[self.args.method]
        else:
            view_method = self.args.method
        self.setWindowTitle(view_method + ' - ' + \
                            self.ClientObj._parent.windowTitle())
        #self.MethodWidget.MainFrameWgt.call_server_method(False)
        #self.MethodWidget.main_frame_view(view, self.args.method,
        #                                    skip_options=not self.args.skip_options)
        self.MethodWidget.main_frame_view(view, self.args.method,
                                          skip_options=self.args.skip_options)
        return 0

    def translate(self, lang = None):
        return 0
    def connect_count_changed(self, host, port, count):
        pass

    def has_update(self, update):
        print("Update", update)

    def get_size(self):
        self.config = ConfigParser.ConfigParser()
        self.config.read(self.user_config)
        try:
            size = self.config.get('gui', 'size')
        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
            return False
        tup_size = map(lambda x: int(x), size.split(','))
        self.resize(tup_size[0], tup_size[1])
        return True

    def set_size(self):
        self.config = ConfigParser.ConfigParser()
        self.config.read(self.user_config)
        try:
            selfsize = self.size()
            self.config.set('gui', 'size',
                "{},{}".format(selfsize.width(), selfsize.height()))
            with open(self.user_config, 'w') as f:
                self.config.write(f)
        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
            return False

    def closeEvent(self, event):
        close_event = self._closeEvent()
#        event.ignore()
        if close_event:
            self.set_size()
            save_path = os.path.join('/tmp', 'calculate-' + \
                                     pwd.getpwuid(os.getuid()).pw_name)
            if os.path.isdir(save_path):
                shutil.rmtree(save_path)
            event.accept()
        else:
            event.ignore()

    def _closeEvent(self):
        if not self.isVisible():
            if self.ClientObj.signaling.isRunning():
                self.ClientObj.signaling.close()
                self.ClientObj.signaling.wait()
            return 1
        if not self.user_changed_flag:
            reply = qt.QMessageBox.Yes
        else:
            reply = self.show_close_messagebox()

        from .mainframe import MainFrame
        if reply == qt.QMessageBox.Yes:
            if hasattr (self, 'con_lost_lbl'):
                self.con_lost_lbl.hide()
                self.con_lost_lbl.close()
            # Exit with closing session
            if self.ClientObj.signaling.isRunning():
                self.ClientObj.signaling.close()
                self.ClientObj.signaling.wait()

            if type (self.MethodWidget.MainFrameWgt) == MainFrame:
                return 1
            else:
                pid = int(self.MethodWidget.MainFrameWgt.cur_pid)
                self.MethodWidget.MainFrameWgt.close()
                self.ClientObj.client.service.pid_kill(pid, self.ClientObj.sid)
                while True:
                    client_pid_info(self.ClientObj, self.ClientObj.client, 0)
                    if 'status' not in self.ClientObj.process_dict[str(pid)]:
                        return 1
                    if self.ClientObj.process_dict[str(pid)]['status'] != '1':
                        return 1
                    time.sleep(1)
        elif reply == qt.QMessageBox.No:
            return 0

    def user_changed(self):
        self.user_changed_flag = True

    def show_close_messagebox(self):
        msgBox = qt.QMessageBox(self)
        if self.method in self.ClientObj.method_names:
            method_name = self.ClientObj.method_names[self.method]
        else:
            method_name = self.method
        msgBox.setText(_("Close") +' "%s"?' %method_name)

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

        # translate
        msgBox.button(msgBox.Yes).setText(_('Yes'))
        msgBox.button(msgBox.No).setText(_('No'))
        icon = get_icon('dialog-close')
        if not icon.isNull():
            msgBox.button(msgBox.No).setIcon(icon)

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

def parse():
    import gettext
    import locale
    try:
        # set_lang = gettext.locale.getdefaultlocale()[0][:2]
        set_lang = locale.getdefaultlocale()[0][:2]
        lang = gettext.translation('cl_consolegui3', languages=[set_lang],fallback=True)
        try:
            lang.install()
            # lang.install(unicode=True)
        except UnboundLocalError:
            pass
    except (IOError, TypeError):
        pass
    _ = gettext.gettext
    import argparse
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument(
        '-h', '--help', action='store_true', default=False,
        dest='help', help=_("show this help message and exit"))
    parser.add_argument( 
        '-l', '--lang', type=str, dest='lang',
        help=_("translation language"))
    parser.add_argument( 
        '--method', type=str, dest='method', 
        help=_('call method'))
    parser.add_argument(
        '--skip-options', action='store_true',
        dest='skip_options', default=False,
        help=_('run the method without options'))
    parser.add_argument(
        '-p', '--port', type=int, dest='port',
        help=_('port number'))      
    parser.add_argument( 
        '--host', type=str, default = 'localhost', dest='host',
        help=_('destination host'))
    return parser


class MyTabBar(qt.QTabBar):
    def __init__(self, _parent):
        super().__init__()
        self._parent = _parent

    def wheelEvent(self, event):
        event.ignore()

    def mousePressEvent(self, event):
        if event.button() == qt.Qt.LeftButton:
            self.setCurrentIndex(self.tabAt(event.pos()))
            event.accept()
        if event.button() == qt.Qt.MiddleButton:
            self._parent.close_tab(self.tabAt(event.pos()))

class ToolTabWidget(qt.QTabWidget):
    def __init__(self, app, args = None, host = None, port = None):
        super().__init__()
        self.app = app
        if args:
            if args.lang:
                self.lang = args.lang

        self.current_icon = None
        self.setContentsMargins(0,0,0,0)
        self.init_variables()

        # Initialization GUI variables
        self.VarsGui = DataVarsGui()
        self.VarsGui.importGui()
        self.VarsGui.flIniFile()

        ClientObj = ApiClient(app, self)
        self.FirstWidget = ClientObj.MainWidget

        self.PlusWidget = qt.QWidget(self)
        self.tabbar = MyTabBar(self)
        self.setTabBar(self.tabbar)

        self.gui_icon = get_icon("video-display")

        self.other_icon = get_icon("list-add", "preferences-desktop")

        self.addTab(self.FirstWidget, self.gui_icon , self.new_con_txt)
        self.addTab(self.PlusWidget, self.other_icon, '')
        self.last_close_index = -1
        self.tabCloseRequested.connect(self.close_tab)
        self.currentChanged.connect(self.add_tab)

        self.currentChanged.connect(self.changeWindowTitle)

        self.setTabsClosable(True)
        self.tabbar.tabButton(1, qt.QTabBar.RightSide).hide()


        if not self.get_size():
            # definition of screen resolution
            prim_screen = self.app.desktop().primaryScreen()
            d_size = self.app.desktop().screenGeometry(prim_screen).size()

            # resize main widget
            if d_size.height() < 768:
                self.resize(900,560)
            else:
                self.resize(dpivalue(900), dpivalue(700))
        self.setMinimumHeight(100)
        self.setMinimumWidth(500)

        self.setWindowTitle(self.Name)

        hbg = get_system_rgb(self, qt.QPalette.Base)
        bg = "transparent"
        leftpadding = 8
        width = 24
        #self.setStyleSheet('''
        #QTabBar::tab:last {
        #background: %s;
        #margin: 2px 2px 3px 0px;
        #width: %s;
        #padding: 0px 0px 0px %spx;}
        #QTabBar::tab:last::hover {
        #    background: %s;}''' % (bg, width, leftpadding, hbg))

        self.set_offline_icon()
        self.show()
        self.app.processEvents()

        self.connect_dict = {}
        self.connect_count = 0
        if not host or host == 'localhost':
            self.host = '127.0.0.1'
        else:
            self.host = host
        if not port:
            self.port = self.VarsGui.GetInteger('core.cl_core_port')
        else:
            self.port = port

        self.setEnabled(False)
        qt.QTimer.singleShot(200, self.connect_after_init)
        self.create_tray()
        if self.FirstWidget.ClientObj.client:
            self.tray.set_icon(True)

    def connect_after_init(self):
        self.FirstWidget.connect_to_localhost(self.host, self.port)
        self.setEnabled(True)
        if self.FirstWidget.ClientObj.client:
            self.FirstWidget.updateColors()
            if self.host in ['127.0.0.1', 'localhost']:
                self.localhost_ClientObj = self.FirstWidget.ClientObj
            if not self.host in self.connect_dict:
                self.connect_dict[self.host] = [self.port]
            else:
                if self.port:
                    if not self.port in self.connect_dict[self.host]:
                        self.connect_dict[self.host].append(self.port)

    def set_offline_icon(self):
        if self.current_icon != "offline":
            self.current_icon = "offline"
            self.setWindowIcon(get_icon(
                '/usr/share/pixmaps/calculate-console-offline.svg'))

    def set_online_icon(self):
        if self.current_icon != "online":
            self.current_icon = "online"
            self.setWindowIcon(get_icon(
                '/usr/share/pixmaps/calculate-console-online.svg'))

    def connect_count_changed(self, host, port, count):
        if count:
            if not host in self.connect_dict:
                self.connect_dict[host] = [port]
            else:
                if port:
                    if not port in self.connect_dict[host]:
                        self.connect_dict[host].append(port)
        else:
            if host in self.connect_dict:
                if port in self.connect_dict[host]:
                    self.connect_dict[host].remove(port)
                if not self.connect_dict[host]:
                    self.connect_dict.pop(host)

        if self.connect_dict:
            self.set_online_icon()
            if hasattr(self, 'tray'):
                self.tray.set_icon(True)
        else:
            self.set_offline_icon()
            if hasattr(self, 'tray'):
                self.tray.set_icon(False)

    def init_variables(self):
        try:
            self.Version = self.VarsGui.Get('cl_ver')
        except:
            self.Version = ''

        #try:
        #    self.Name = self.VarsGui.Get('cl_name')
        #except:
        self.Name = 'Calculate Console'

        self.new_con_txt = _('New connection')
        self.sys_update_pid = None

    def close_tab(self, cur_num = None, hard = False):
        exit_flag = 0
        if cur_num == None:
            cur_num = self.currentIndex()

        if cur_num != self.count() - 1:
            # for delete widget
            self.setCurrentIndex(cur_num)
            wgt = self.currentWidget()

            if wgt == self.FirstWidget and not hard:
                return exit_flag
            if wgt._closeEvent():
                wgt.close()

                self.last_close_index = cur_num
                if cur_num:
                    self.setCurrentIndex(cur_num - 1)
                else:
                    self.setCurrentIndex(0)
                self.removeTab(cur_num)
                exit_flag = 1
        if self.count() < 2:
            self.add_tab()
        return exit_flag

    def add_tab(self):
        if self.currentIndex() == self.count() - 1:
            # not add if exists clean tab
            for tab_num in range(self.count() - 1):
                self.setCurrentIndex(tab_num)
                if not self.currentWidget().ClientObj.client:
                    return 0

            ClientObj = ApiClient(self.app, self)
            widget = ClientObj.MainWidget
            widget.cur_window_title = self.Name

            self.insertTab(self.count() - 1, widget, self.gui_icon , \
                                                      self.new_con_txt)
            self.setCurrentIndex(self.count() - 2)
        if self.currentWidget().ClientObj.client:
            self.tabbar.setTabEnabled(self.count() - 1, True)
        else:
            self.tabbar.setTabEnabled(self.count() - 1, False)

    def rename_tab(self, text = None, ind = None):
        if not text:
            text = self.new_con_txt
        if not ind:
            ind = self.currentIndex()
        self.setTabText(ind, text)

    def changeWindowTitle(self, tab_num):
        try:
            text = self.currentWidget().cur_window_title
            self.setWindowTitle(text)
        except AttributeError:
            pass

    def setWindowTitle(self, title):
        self.currentWidget().cur_window_title = title
        super(ToolTabWidget, self).setWindowTitle(title)

    def create_tray(self):
        self.tray = TrayIcon(self)
        self.tray.setVisible(True)
        self.app.processEvents()

    def translate(self, lang = None):
        self.new_con_txt = _('New connection')
        # self.new_con_txt = self.new_con_txt.decode('utf-8')

        current = self.currentIndex()
        # not add if exists clean tab
        for tab_num in range(self.count() - 1):
            self.setCurrentIndex(tab_num)
            if not self.currentWidget().ClientObj.client:
                self.setTabText(tab_num, self.new_con_txt)
        self.setCurrentIndex(current)

        if hasattr(self, 'tray'):
            self.tray.translate()

    def set_localhost(self, ClientObj):
        self.localhost_ClientObj = ClientObj
#        if ClientObj:
#            self.connect_dict[ClientObj.host_name] = \
#                             [ClientObj, self.currentIndex()]
#        self.tabbar.tabButton(self.currentIndex(), \
#                              qt.QTabBar.RightSide).hide()

    def find_host(self, host_name, port):
        ind = self.currentIndex()
        for i in range (self.count() - 1):
            self.setCurrentIndex(i)
            wgt = self.currentWidget()
            if hasattr (wgt, 'ClientObj'):
                ClientObj = wgt.ClientObj
                if host_name == ClientObj.host_name and \
                                port == ClientObj.port and ClientObj.client:
                    self.removeTab(ind)
                    return 1

        self.setCurrentIndex(ind)
        return 0

    def closeEvent(self, event):
        self.cur_pos = self.pos()
        self.hide()
        from os import environ
        if environ.get("XSESSION","").lower() == "plasma":
            event.accept()
        else:
            event.ignore()

    def _closeEvent(self):
            for tab_num in range(self.count()):
                if not self.close_tab(0, True):
                    return 1
            self.set_size()
            save_path = os.path.join('/tmp', 'calculate-' + \
                                     pwd.getpwuid(os.getuid()).pw_name)
            if os.path.isdir(save_path):
                shutil.rmtree(save_path)
            self.app.exit()

    def get_size(self):
        conf_path = self.VarsGui.Get('cl_gui_config_path')
        homePath = self.VarsGui.Get('ur_home_path')
        self.user_config = conf_path.replace("~",homePath)
        self.config = ConfigParser.ConfigParser()
        self.config.read(self.user_config)
        try:
            size = self.config.get('gui', 'size')
        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
            return False
        tup_size = list(map(lambda x: int(x), size.split(',')))
        self.resize(tup_size[0], tup_size[1])
        return True

    def set_size(self):
        self.config = ConfigParser.ConfigParser()
        self.config.read(self.user_config)
        try:
            selfsize = self.size()
            self.config.set('gui', 'size',
                "{},{}".format(selfsize.width(), selfsize.height()))
            with open(self.user_config, 'w') as f:
                self.config.write(f)
        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
            return False

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