#!/usr/bin/python3.5
# Copyright 2017 Digital
#
# This file is part of DigiLib.
#
# DigiLib is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DigiLib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with DigiLib.  If not, see <http://www.gnu.org/licenses/>.
#
## Imports
# Python Libraries
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
import logging
import logging.config
import os
import pprint
import random
import string
import sys
import time
import yaml
# My libraries
import digilib.misc
## Logging
log = logging.getLogger(__name__+".gui")
## Global Variables
## Classes

class LabelName(Gtk.Label):
    def __init__(self, *args,**kwargs):
        super(LabelName, self).__init__(*args,**kwargs)
        self.set_css_name("namelabel")
        self.set_halign(Gtk.Align(2))

class LabelValue(Gtk.Label):
    """docstring for LabelValue"""

    def __init__(self, *args,**kwargs):
        super(LabelValue, self).__init__(*args,**kwargs)
        self.set_css_name("valuelabel")
        self.set_halign(Gtk.Align(1))

class InfoFrame(Gtk.Frame):
    """docstring for InfoFrame."""
    def __init__(self,**kwargs):
        super(InfoFrame, self).__init__(**kwargs)
        self.lines = {
            # id:{
            #     "layout": layout,
            #     "widgets": [label_name,label_value,widget],
            #     "update_func":widget_update_func
            # }
        }
        self.current_line_no = 0
        # self.layout = Gtk.Grid(halign=Gtk.Align(1))
        self.layout = Gtk.Grid()
        self.layout.set_row_spacing(10)
        self.layout.set_column_spacing(5)
        self.layout.set_column_homogeneous(False)
        self.layout.set_hexpand(True)
        self.add(self.layout)
    def add_line(
            self,
            identifier,
            name,
            value,
            unit=None,
            widget=None,
            widget_update_func=None
        ):
        if id in self.lines.keys():
            raise ValueError(
                "Identifiers must be uniqe, but '"
                +identifier
                +"' already exists!"
            )
        self.lines[identifier] = {
        "layout":None,
        "wname":None,
        "wvalue":None,
        "wunit":None,
        "wextra":None,
        "update_func":None
        }
        self.lines[identifier]["update_func"] = widget_update_func
        # if there is a widget and an update function was passed then update it

        if widget_update_func == True:
            self.lines[identifier]["update_func"] = widget.set_value
        if self.lines[identifier]["update_func"]:
            self.lines[identifier]["update_func"](value)
        layout = Gtk.Box()
        layout.set_spacing(5)
        layout.set_homogeneous(False)
        self.lines[identifier]["layout"] = layout
        # create the labels for the name and value field and also for the unit
        # field if an unit was specified
        label_name = LabelName(name)
        self.lines[identifier]["wname"] = label_name
        self.layout.attach(label_name,0,self.current_line_no,1,1)
        label_value = LabelValue(value)
        self.lines[identifier]["wvalue"] = label_value
        layout.add(label_value)
        if unit:
            label_unit = LabelValue(unit)
            self.lines[identifier]["wunit"] = label_unit
            layout.add(label_unit)
        if widget:
            self.lines[identifier]["wextra"] = widget
            layout.add(widget)
        self.layout.attach(layout,1,self.current_line_no,1,1)
        self.current_line_no += 1
    def update_name(self,identifier,name):
        self.lines[identifier]["wname"].set_label(name)
    def update_unit(self,identifier,unit):
        self.lines[identifier]["wunit"].set_label(unit)
    def update_value(self,identifier,value):
        self.lines[identifier]["wvalue"].set_label(str(value))
        if self.lines[identifier]["update_func"]:
            self.lines[identifier]["update_func"](value)
        print(1)

# class ChildGrid(Gtk.Grid):
#     def __init__(self):
#         super(ChildGrid,self).__init__()
#         self.prepare()
#     def prepare(self):
#         pass
#
# class ChildScrollBase(Gtk.ScrolledWindow):
#     def __init__(self):
#         super(ChildScroll,self).__init__()
#         self.prepare()
#     def prepare(self):
#         pass

class ChildConsole(Gtk.Grid):
    scroll = True
    history_list = []
    history_position = -1
    def __init__(self,get_client):
        super(ChildConsole,self).__init__()
        self.get_client = get_client
        self.set_css_name("tab_console")
        self.prepare()
        self.button_send.connect("clicked",self.on_entry_activated)
        self.entry_cmd.connect("activate",self.on_entry_activated)
        self.entry_cmd.connect("key-press-event",self.on_keypress)
    def prepare(self):
        self.scroll_mark = Gtk.TextMark(name="scroll_mark")
        self.text_buffer_log = Gtk.TextBuffer()
        self.text_view_log = Gtk.TextView(hexpand=True,vexpand=True)
        self.text_view_log.set_buffer(self.text_buffer_log)
        self.text_view_log.set_editable(False)
        self.text_view_log.set_cursor_visible(False)
        self.text_view_log.props.pixels_above_lines = 2
        self.text_view_log.props.pixels_below_lines = 2
        self.text_view_log.props.right_margin = 2
        self.text_view_log.props.left_margin = 6
        # self.text_view_log.set_hexpand(True)
        # self.text_view_log.set_vexpand(True)
        self.scrolled_window = Gtk.ScrolledWindow()
        self.entry_cmd = Gtk.Entry(hexpand=True)
        # self.entry_cmd.set_cursor_hadjustment(Gtk.Align(2))
        # self.entry_cmd.set_hexpand(True)
        self.button_send = Gtk.Button(label="send")
        # self.button_send.set_label("send")
        self.scrolled_window.add(self.text_view_log)
        self.attach(self.scrolled_window,0,1,2,1)
        self.attach(self.entry_cmd,0,2,1,1)
        self.attach(self.button_send,1,2,1,1)
    def add_msg(self,text,sender_name="Server"):
        for line in text.splitlines():
            if sender_name:
                line = sender_name+":"+line
            self.text_buffer_log.insert(
                self.text_buffer_log.get_end_iter(),
                "\n"+line.rstrip()
            )
            self.scroll_down(None)
        if self.scroll:
            self.scroll_down(None)
    def add_msg_threadsafe(self,*args,**kwargs):
        Gdk.threads_enter()
        self.add_msg(*args,**kwargs)
        Gdk.threads_leave()
    def send(self,text):
        client = self.get_client()
        if client:
            if client.is_connected:
                client.send(text)
    def scroll_down(self,*args):
        self.scroll = True
        self.text_buffer_log.add_mark(
            self.scroll_mark,
            self.text_buffer_log.get_end_iter()
        )
        self.text_view_log.scroll_to_mark(
            mark=self.scroll_mark,
            # No idea what these arguments do, but they work.
            within_margin=0.0,
            use_align=True,
            xalign=0.5,
            yalign=0.5
        )
        self.text_buffer_log.delete_mark(self.scroll_mark)
    def toggle_scroll(self,*args):
        self.scroll = not self.scroll
    def get_entry_text(self):
        text = self.entry_cmd.get_text()
        self.entry_cmd.set_text("")
        return text
    def on_entry_activated(self,widget):
        text = self.get_entry_text()
        if text.strip():
            self.history_position = -1
            if len(self.history_list) == 0:
                self.history_list.insert(0,text)
            else:
                if self.history_list[0] != text:
                    self.history_list.insert(0,text)
            self.add_msg(text,"you")
            self.send(text)
    def on_keypress(self,widget,event):
        if not widget == self.entry_cmd:
            lgui.debug("exiting keypress event function because the widget was \
                not self.entry_cmd")
            return True
        if event.keyval == Gdk.KEY_Up: # Up
            if self.history_position < len(self.history_list)-1:
                self.history_position += 1
                text = self.history_list[self.history_position]
                self.entry_cmd.set_text(text)
                self.entry_cmd.set_position(len(text))
            return True
        elif event.keyval == Gdk.KEY_Down: # Down
            text = self.entry_cmd.get_text()
            if self.history_position == -1 and text != "":
                self.entry_cmd.set_text("")
            elif self.history_position == 0:
                self.history_position = -1
                self.entry_cmd.set_text("")
            elif  self.history_position > 0:
                self.history_position -= 1
                text = self.history_list[self.history_position]
                self.entry_cmd.set_text(text)
                self.entry_cmd.set_position(len(text))
            return True

class ChildOverview(Gtk.ScrolledWindow):
    def __init__(self):
        super(ChildOverview,self).__init__()
        self.set_css_name("tab_overview")
        self.layout = Gtk.Grid()
        self.layout.set_column_homogeneous(True)
        self.add(self.layout)

class ChildControl(Gtk.Grid):
    def __init__(self):
        super(ChildControl,self).__init__()
        self.label = Gtk.Label()
        self.label.set_markup("<big>Another fancy self.label</big>")
        self.add(self.label)

class ChildSettings(Gtk.Grid):
    def __init__(self):
        super(ChildSettings,self).__init__()
        self.label = Gtk.Label()
        self.label.set_markup("<big>Another fancy self.label</big>")
        self.add(self.label)

class WindowBase(Gtk.Window):
    def __init__(self,title="Don't Panic!"):
        super(Gtk.Window,self).__init__(title=title)
        self.pressed_keys = []
        self.key_shortcuts = []
        self.connect("delete-event",self.on_delete_event)
        self.connect("key-press-event",self.on_key_press_event)
        self.connect("key-release-event",self.on_key_release_event)
    def keystring_to_gkd(self, keys):
        key_list = keys.split(" ")
        known_keys = []
        unknown_keys = []
        for k in key_list:
            if "KEY_"+k in dir(Gdk):
                known_keys.append(eval("Gdk.KEY_"+k))
            else:
                unknown_keys.append(k)
        if unknown_keys:
            raise ValueError("Unknown Keys: "+", ".join(unknown_keys))
        else:
            return known_keys
    def add_key_shortcut(self,keys,func=None,args=[],kwargs={}):
        key_list = self.keystring_to_gkd(keys)
        for ks in self.key_shortcuts:
            if key_list == ks[0]:
                self.key_shortcuts.remove(ks)
                break
        self.key_shortcuts.append([key_list,func,args,kwargs])
    def remove_key_shortcut(self,keys):
        key_list = self.keystring_to_gkd(keys)
        for ks in self.key_shortcuts:
            if key_list == ks[0]:
                self.key_shortcuts.remove(ks)
                break
    def on_delete_event(self,*args):
        print(args)
        Gtk.main_quit()
    def on_key_release_event(self,widget,event):
        if event.keyval in self.pressed_keys:
            self.pressed_keys.remove(event.keyval)
    def on_key_press_event(self,widget,event):
        self.pressed_keys.append(event.keyval)
        for keys,func,args,kwargs in self.key_shortcuts:
            if keys == self.pressed_keys:
                func(*args,**kwargs)
                break
    def hello_world(self,*args):
        print("hello world")






























#