#-*- 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.

import dbus
import dbus.service
import dbus.mainloop.glib

from calculate.consolegui import qt
import sudsds, time, sys
import os, pwd, shutil
import ConfigParser

from TrayIcon import TrayIcon

from more import get_sid, get_view_params, _print, get_icon, get_system_rgb
    
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__])

class SelectedMethodWgt(qt.QWidget):
    def __init__(self, app, args):
        qt.QWidget.__init__(self)
        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 sudsds.MethodNotFound:
            _print('Method not found: ', self.args.method + '_view')
            self.close()
            sys.exit(1)
        if self.ClientObj.method_names.has_key(self.args.method):
            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()))
            self.config.write(open(self.user_config, 'w'))
        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 not self.ClientObj.process_dict[str(pid)].has_key \
                                                                ('status'):
                        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.ClientObj.method_names.has_key(self.method):
            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
    try:
        set_lang = gettext.locale.getdefaultlocale()[0][:2]
        lang = gettext.translation('cl_consolegui3', languages=[set_lang],fallback=True)
        try:
            lang.install(unicode=True)
        except UnboundLocalError:
            pass
    except (IOError, TypeError):
        pass

    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):
        qt.QTabBar.__init__(self)
        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):
        qt.QTabWidget.__init__(self)
        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(900, 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 xrange (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 = 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()))
            self.config.write(open(self.user_config, 'w'))
        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)
