#-*- 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 calculate.consolegui import qt

from more import ButtonMenu, FlowLayout, get_sid, ClientServiceThread, \
                 get_view_params, show_msg, client_list_methods, get_system_rgb, \
                 get_icon

class DisplayMethod(qt.QWidget):
    def __init__(self, parent, ClientObj):
        super(DisplayMethod, self).__init__(parent)
        self.ClientObj = ClientObj
        self._parent = parent
        self.setAttribute(qt.Qt.WA_DeleteOnClose)
        ClientObj.back_step_list = []

    def initUI(self, results):
        GROUP = 0 # Getting group name
        METH = 1 # Getting method name
        LABEL = 2 # Get translate label
        IMAGE = 3 # Getting image path
        self.lable_list = []
        self.button_list = {}
        self.layout = qt.QVBoxLayout()
        self.groupbox_dict = {}
        self.layout_dict = {}

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


        groupbox_style = "QGroupBox { padding-top: 24px; padding-left: 10px;}"

        # transform a list into the dictionary {'group': [methods], ...}
        guiMethods = {}
        if type(results) == int:
#            self.layout.addWidget(LabelWordWrap(_('No Methods!'),self))
            self.setLayout(self.layout)
            self.show()
            return 1
        for num in range (0, len(results)):
            groups_name = results[num].string[GROUP]
            if results[num].string[GROUP] in [None,'None']:
                self.ClientObj.method_names[results[num].string[METH]] = \
                                        results[num].string[LABEL]
                continue
            if not groups_name in guiMethods.keys():
                guiMethods[groups_name] = []
            self.ClientObj.method_names[results[num].string[METH]] = \
                                        results[num].string[LABEL]
            guiMethods[groups_name].append(results[num].string[METH])
            guiMethods[groups_name].append(results[num].string[LABEL])
            guiMethods[groups_name].append(results[num].string[IMAGE])

        # display all groups and methods
        for group in guiMethods:
            if len (group.split('.')) > 1:
                group_name = group.split('.')[0].encode('utf-8')
                sub_group = group.split('.')[1].encode('utf-8')
                if not self.groupbox_dict.has_key(group_name):
                    gb = qt.QGroupBox(group_name.decode('utf-8'), self)
                    gb.setStyleSheet(groupbox_style)
                    gb.setAlignment(qt.Qt.AlignLeft)
                    self.groupbox_dict[group_name] = gb

                if not self.layout_dict.has_key(group_name):
                    self.layout_dict[group_name] = \
                                    FlowLayout(self.groupbox_dict[group_name])

                attrubute_list = []
                sub_group_list = []
                if self.button_list.has_key(sub_group):
                    attrubute_list = self.button_list[sub_group][0]
                    sub_group_list = self.button_list[sub_group][1]
                self.button_list[sub_group] = []
                self.button_list[sub_group].append \
                        (attrubute_list + guiMethods[group])
                sub_group_list.append(group.split('.',1)[1].encode('utf-8'))
                self.button_list[sub_group].append \
                        (sub_group_list)

                Button = ButtonMenu(sub_group, sub_group, \
                                    'folder-documents,folder', self)
                Button.clicked.connect(self.groupActivated \
                                    (self.button_list[sub_group][0], \
                                     self.button_list[sub_group][1]))
#                try:
#                    Button.setStatusTip(sub_group.decode('utf-8'))
#                except (UnicodeDecodeError, UnicodeEncodeError):
#                    Button.setStatusTip(sub_group)

                self.button_list[sub_group].append(Button)
                continue

            if not self.groupbox_dict.has_key(group):
                gb = qt.QGroupBox(group, self)
                gb.setStyleSheet(groupbox_style)
                self.groupbox_dict[group] = gb
                gb.setAlignment(qt.Qt.AlignLeft)

            if not self.layout_dict.has_key(group):
                self.layout_dict[group] = FlowLayout(self.groupbox_dict[group])
            view_name_sort = filter(lambda x: guiMethods[group].index(x) % 3 \
                                    == 1, guiMethods[group])
            view_name_sort.sort()
            guiMethods_sort = []
            for sort_name in view_name_sort:
                ind = guiMethods[group].index(sort_name)
                for i in range(ind-1, ind+2):
                    guiMethods_sort.append(guiMethods[group][i])
            for method_name in range (0, len(guiMethods_sort), 3):
                Button = ButtonMenu(guiMethods_sort[method_name],\
                                guiMethods_sort[method_name + 1], \
                                guiMethods_sort[method_name + 2], \
                                self)
                Button.clicked.connect(self.onActivated)

#                try:
#                    Button.setStatusTip(sub_group.decode('utf-8'))
#                except (UnicodeDecodeError, UnicodeEncodeError):
#                    Button.setStatusTip(sub_group)
 
                if not self.button_list.has_key(group):
                    self.button_list[group] = []
                self.button_list[group].append(Button)

                self.layout_dict[group].addWidget \
                                (self.button_list[group]\
                                [len(self.button_list[group]) - 1])

            self.layout_dict[group].setAlignment(qt.Qt.AlignLeft | \
                                                       qt.Qt.AlignTop)
            self.groupbox_dict[group].setLayout(self.layout_dict[group])

        keys_sort = guiMethods.keys()
        keys_sort.sort()
        for group in keys_sort:
            if len (group.split('.')) > 1:

                group_name = group.split('.')[0].encode('utf-8')
                sub_group = group.split('.')[1].encode('utf-8')

#                for i in range (20):
#                    self.layout_dict[group_name].addWidget(ButtonMenu \
#                                ('gggggggg',\
#                                'qqqqww wwwww', \
#                                'code-block', \
#                                self))
                self.layout_dict[group_name].addWidget \
                                (self.button_list[sub_group]\
                                [len(self.button_list[sub_group]) - 1])

                self.layout_dict[group_name].setAlignment(qt.Qt.AlignLeft)
                if self.groupbox_dict[group_name]:
                    self.groupbox_dict[group_name].setLayout \
                                                (self.layout_dict[group_name])

                if self.groupbox_dict[group_name]:
                    self.layout.addWidget(self.groupbox_dict[group_name])
                    self.groupbox_dict[group_name] = None
                continue
            elif self.groupbox_dict[group]:
                self.layout.addWidget(self.groupbox_dict[group])
                self.groupbox_dict[group] = None

        self.layout.setAlignment(qt.Qt.AlignTop)
        self.setLayout(self.layout)
        self.resize(self.layout.sizeHint())
        self.updateColors()

    def updateColors(self):
        background_color = get_system_rgb(self._parent.main_frame, qt.QPalette.Base)
        self._parent.main_frame.viewport().setStyleSheet(
            "background-color: %s ; " %background_color
        )
        text_color = "rgb(160,160,160)"
        self.setStyleSheet(self.styleSheet() + \
            'QWidget { background: transparent;}'

            'QGroupBox {font-weight: bold;'
            'border: 1px solid gray;'
            'border-left-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1,'
                                        'stop: 0 gray, stop: 1 transparent);'
            'border-top-color: qlineargradient( x1: 0, y1: 0, x2: 1, y2: 0,'
                                       'stop: 0 gray, stop: 1 transparent);'
            'border-right: 0px; border-bottom: 0px;'
            'border-top-left-radius: 2px;'

            'background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,'
            'stop: 0 rgba(200, 200, 200,75), stop: 0.5 transparent,'
            'stop: 1 transparent);'
            'padding-top: 18px; padding-bottom: 18px;}'
            'QGroupBox::title {background-color: transparent;'

            'color: %s; subcontrol-position: top left;'
            'margin-top: 6px; margin-left: 8px;}'%text_color)

        for group in self.button_list.values():
            for button in group:
                button.updateColors()

    def disableButtons(self):
        for group in self.button_list.values():
            for button in group:
                button.setEnabled(False)
                button.updateColors()

    def refresh(self):
        self.ClientObj.methods_list = client_list_methods(self.ClientObj.sid,
            self.ClientObj.client)
        results = self.ClientObj.methods_list
        self.initUI(results)
        self.ClientObj.app.processEvents()

        self.ClientObj.MainWidget.left_frame.cur_palette = \
                    self._parent.main_frame.viewport().palette()
        self.ClientObj._parent.setWindowTitle(_("Calculate Console"))


    def onActivated(self):
        # Call server method
        if hasattr (self, 'onActivated_thread'):
            if self.onActivated_thread.isRunning():
                return 1
        self.setEnabled(False)
        self.updateColors()
        method_name = self.sender().objectName()
#        view_method_name = self.sender().text()
        step = 0
        brief = False
        self.ClientObj.method_name = method_name

        self.ClientObj.sid = get_sid(self.ClientObj.client)
        expert = None
        if self.ClientObj.param_objects.has_key(method_name):
            self.ClientObj.param_objects[method_name]['step'] = 0
            if self.ClientObj.param_objects[method_name]['expert_changed']:
                expert = True


        view_params = get_view_params(self.ClientObj.client, \
                       str(method_name + '_view'), step = step,
                       expert = expert,
                       brief = brief)
        self.onActivated_thread = ClientServiceThread(self.ClientObj, \
                        str(method_name + '_view'), int(self.ClientObj.sid), \
                        view_params, return_except = True)
        self.onActivated_thread.signal.connect(self.onActivated_after)
        self.onActivated_thread.start()

    def onActivated_after(self, view):
        self.setDisabled(False)
        #self.con_lost_lbl.hide()
        if type(view) == Exception:
            if hasattr (view.message, 'message'):
                view = view.message

            if type(view.message) == tuple:
                if view.message[0] == 403:
                    msg = _('Permission denied')
                else:
                    msg = ' '.join(map(lambda x: str(x), view.message))
            else:
                msg = view.message.__str__()
            show_msg(msg)
            return 1

        method_name = self.ClientObj.method_name
        self._parent.main_frame.viewport().setStyleSheet('')

        # set new Title
        if self.ClientObj.method_names.has_key(method_name):
            view_method = self.ClientObj.method_names[method_name]
        else:
            view_method = method_name
        self.ClientObj._parent.setWindowTitle \
                (view_method + ' - ' + self.ClientObj._parent.windowTitle())
        self.ClientObj.MainWidget.main_frame_view(view, method_name)

    def groupActivated(self, groups, sub_group, back = False):
        def wrapper():
            self._parent.main_frame.viewport().setStyleSheet('')
            self.ClientObj.MainWidget.delete_MainFrameWgt()

            self.ClientObj.MainWidget.MainFrameWgt = \
                                      qt.QWidget(self.ClientObj.MainWidget)
            if not back:
                # save data for a step back
                self.ClientObj.back_step_list.append ([groups, sub_group, \
                                    self.ClientObj._parent.windowTitle()])

            hlayout = qt.QHBoxLayout()
            hlayout.addItem(qt.QSpacerItem( 0, 0, \
                    qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding))
            self.ClientObj.MainWidget.MainFrameWgt.setLayout(hlayout)

            self.ClientObj.MainWidget.main_frame.setWidget \
                                    (self.ClientObj.MainWidget.MainFrameWgt)
            self.ClientObj.MainWidget.main_frame.setWidgetResizable(True)

            self.ClientObj.MainWidget.left_frame.update()
            self.ClientObj.MainWidget.left_frame.show()

            try:
                new_title = sub_group[0].split('.')[0].decode('utf-8')
            except (UnicodeDecodeError, UnicodeEncodeError):
                pass
            if self.ClientObj.MainWidget.left_frame.old_title:                
                self.ClientObj._parent.setWindowTitle(new_title +' - '+ \
                               self.ClientObj.MainWidget.left_frame.old_title)
            else:
                self.ClientObj._parent.setWindowTitle(new_title + ' - ' + \
                                       self.ClientObj._parent.windowTitle())
            self.ClientObj.MainWidget.left_frame.create_menu \
                                    (self, groups, sub_group, self.ClientObj)
        return wrapper

    def closeEvent(self, event):
        self._parent.main_frame.viewport().setStyleSheet ('')
        if hasattr (self, 'onActivated_thread'):
            if self.onActivated_thread.isRunning():
                self.onActivated_thread.close()
                self.onActivated_thread.wait()
        event.accept()

class StartWidget(qt.QWidget):
    def __init__(self, parent):
        super(StartWidget, self).__init__(parent)
        self.setAttribute(qt.Qt.WA_DeleteOnClose)

class ConnectLostLabel (qt.QWidget):
    def __init__(self, text, parent, reconnect = False):
        qt.QWidget.__init__(self, parent.layout_wgt)
        self._parent = parent
        if parent.main_frame.isEnabled():
            parent.left_frame.setDisabled(True)
            parent.main_frame.setDisabled(True)
            parent.control_button.setDisabled(True)

        white_layout = qt.QVBoxLayout(self)
        lbl = qt.QLabel(text + '\n\n', self)
        white_layout.addWidget(lbl)

        self.setStyleSheet ('background-color: rgba(250,250,250,200);'
                            'border-radius: 2px;')

        if reconnect:
            self.reconnect_button = qt.QPushButton(_('Reconnect'), self)
            self.reconnect_button.setIcon(get_icon('view-refresh'))
            self.reconnect_button.setStyleSheet('''
            QPushButton {
                 border: 2px solid #8f8f91;
                 border-radius: 6px;
                 background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                   stop: 0 #f6f7fa, stop: 1 #dadbde);
                 min-width: 80px; }

            QPushButton:pressed {
                 background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                   stop: 0 #dadbde, stop: 1 #f6f7fa);}

            QPushButton:flat {border: none;}
            QPushButton:default {border-color: navy;} ''')
            self.reconnect_button.clicked.connect \
                                              (self._parent.reconnect_to_host)
            self.reconnect_button.move(parent.layout_wgt.size().width()/2 - \
                                   self.reconnect_button.sizeHint().width()/2,\
                                   parent.layout_wgt.size().height()/2 + \
                                   self.reconnect_button.sizeHint().height())

            self.reconnect_button.resize(self.reconnect_button.sizeHint() + \
                                         qt.QSize(5,5))
            self.reconnect_button.show()
            self.reconnect_button.setEnabled(True)

        lbl.setAlignment(qt.Qt.AlignCenter)
        self.move(-10,-10)
        self.resize(parent.layout_wgt.size() + qt.QSize(20,20))

        self.setEnabled(True)

    def resize_widget(self):
        cur_size = self._parent.size()
        self.resize(cur_size + qt.QSize(20,20))
        if hasattr (self, 'reconnect_button'):
            self.reconnect_button.move(cur_size.width()/2 - \
                                   self.reconnect_button.sizeHint().width()/2,\
                                   cur_size.height()/2 + \
                                   self.reconnect_button.sizeHint().height())
