#!/usr/bin/python3

import os
import sys
import time
import datetime
import wx

class shared_data:
    def __init__(self):
        #This is a temporary fudge soon to be cleaned and used more widely
        #
        ## paths
        #
        # gui system paths
        shared_data.cwd = os.getcwd()
        shared_data.ui_img_path = os.path.join(shared_data.cwd, "ui_images")
        shared_data.graph_modules_path = os.path.join(shared_data.cwd, "graph_modules")
        sys.path.append(shared_data.graph_modules_path)
        shared_data.graph_presets_path = os.path.join(shared_data.cwd, "graph_presets")
        localpath = str(os.getcwd()).split("/scripts")[0]
        print (localpath)
        shared_data.local_logs_path = os.path.join(localpath, "logs")
        local_graphs_path = os.path.join(localpath, "graphs")
        shared_data.local_graph_path = os.path.join(local_graphs_path, "live_rolling.png")
        #shared_data.local_graph_path = "/home/pragmo/frompigrow/carputer/graphs/live_rolling.png"
        #
        ## Fonts
        #
        shared_data.title_font = wx.Font(28, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
        shared_data.sub_title_font = wx.Font(15, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
        shared_data.item_title_font = wx.Font(16, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
        shared_data.info_font = wx.Font(14, wx.MODERN, wx.ITALIC, wx.NORMAL)
        shared_data.large_info_font = wx.Font(16, wx.MODERN, wx.ITALIC, wx.NORMAL)
        #
        ## Options
        #
        graph_data_option = "DHT22_Temp.txt"
        shared_data.graph_data_preset_choice = os.path.join(shared_data.graph_presets_path, graph_data_option)
        show_duration = 2 #hours
        #
        ## Data
        #
        shared_data.list_of_datasets = []





class display_pnl(wx.Panel):
    """
    This panel displays the most recent information from the selected graph module or datawall
    """
    #
    #
    def __init__( self, parent ):
        wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL )
        # timer
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.update, self.timer)
        # Tab Title
        title_l = wx.StaticText(self,  label='Live Display', size=(-1,40))
        title_l.SetBackgroundColour((50,250,250))
        title_l.SetFont(shared_data.title_font)
        self.toggleBtn = wx.Button(self, wx.ID_ANY, "Start")
        self.toggleBtn.Bind(wx.EVT_BUTTON, self.onToggle)
        bitmap = wx.Bitmap(1, 1)
        #bitmap.LoadFile(pic_one, wx.BITMAP_TYPE_ANY)
        size = bitmap.GetSize()
        self.img_bmp_box = wx.StaticBitmap(self, -1, bitmap, size=(size[0], size[1]))


        # sizers
        self.image_sizer = wx.BoxSizer(wx.VERTICAL)
        self.image_sizer.Add(self.img_bmp_box, 0, wx.EXPAND, 3)

        main_sizer = wx.BoxSizer(wx.VERTICAL)
        main_sizer.Add(title_l, 0, wx.ALIGN_CENTER_HORIZONTAL, 3)
        main_sizer.Add(self.toggleBtn, 0, wx.ALIGN_CENTER_HORIZONTAL, 3)
        main_sizer.Add(self.image_sizer, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 3)
        self.SetSizer(main_sizer)

    def load_log_from_preset(self, preset_path):
        # create dictionary of preset settings
        with open(shared_data.graph_data_preset_choice) as f:
            graph_presets = f.read()
        graph_presets = graph_presets.splitlines()
        preset_settings = {}
        for line in graph_presets:
            if "=" in line:
                equals_pos = line.find("=")
                key = line[:equals_pos]
                value = line[equals_pos + 1:]
                preset_settings[key]=value
        # Setting basic values
        try:
            log_to_load = preset_settings['log_path']
            split_chr = preset_settings['split_chr']
            date_pos = int(preset_settings['date_pos'])
            value_pos = int(preset_settings['value_pos'])
            key_pos = preset_settings['key_pos']
        except:
            print("Split_chr, Date, Value, Key position not set for reading data, can't continue")
            return [[], [], []]
        if not key_pos.isdigit():
            key_pos = ""
        else:
            key_pos = int(key_pos)
        #
        try:
            date_split = preset_settings['date_split']
            date_split_pos = preset_settings['date_split_pos']
        except:
            date_split = ""
            date_split_pos = ""
        #
        try:
            value_split = preset_settings['value_split']
            value_split_pos = preset_settings['value_split_pos']
        except:
            value_split = ""
            value_split_pos = ""
        try:
            key_split = preset_settings['key_split']
            key_split_pos = preset_settings['key_split_pos']
        except:
            key_split = ""
            key_split_pos = ""
        #
        if "value_rem" in preset_settings:
            value_rem = preset_settings['value_rem']
        else:
            value_rem = ""
        if "key_match" in preset_settings:
            key_match = preset_settings['key_match']
        else:
            key_match = ""
        if "key_manual" in preset_settings:
            key_manual = preset_settings['key_manual']
        else:
            key_manual = ""
        ##
        #    Hige and Low values are currently ignored - this should be added in here
        ##
        #
        ## Load data from the log
        #

        log_path = os.path.join(shared_data.local_logs_path, log_to_load)
        #log_path = "/home/pragmo/frompigrow/carputer/logs/dht22_log.txt"
        print("  -- Reading log from file " + log_path)
        with open(log_path) as f:
            log_to_parse = f.read()
        log_to_parse = log_to_parse.splitlines()
        if len(log_to_parse) == 0:
            print("  --- Log file is empty")
        else:
            print("  --- Log contains " + str(len(log_to_parse)) + " lines")
        #
        ##
        #
        numbers_only = True
        limit_by_date = False
        # define lists to fill
        date_list = []
        value_list = []
        key_list = []
        # cycle through each line and fill the lists
        for line in log_to_parse:
            line_items = line.split(split_chr)
            # get date for this log entry
            date = line_items[date_pos]
            if not date_split == "":
                date = date.split(date_split)[date_split_pos]
            if "." in date:
                date = date.split(".")[0]
            # Check date is valid and ignore if not
            try:
                date = datetime.datetime.strptime(date, '%Y-%m-%d %H:%M:%S')
                if limit_by_date == True:
                    if date > last_datetime or date < first_datetime:
                        date = ""
            except:
                #raise
                print("date not valid -" + str(date))
                date = ""

            # get value for this log entry
            value = line_items[value_pos]
            if not value_split == "":
                value = line_items[value_pos]
                value = value.split(value_split)[value_split_pos]
            # remove from value
            if not value_rem == "":
                value = value.replace(value_rem, "")
            # perform checks for numbers only when selected
            if numbers_only == True:
                try:
                    value = float(value)
                except:
                    print('value not valid -' + str(value))
                    raise
                    value = ""

            # get key for this log entry
            if not key_pos == "":
                key = line_items[key_pos]
                if not key_split == "":
                    key = key.split(key_split)[key_pos_split]
                # if key matching is selected
                if not key_match == "":
                    if not key_match in key:
                        key = False
            # if manual key is selected
            elif not key_manual == "":
                key = key_manual
            elif key_pos == "" and key_manual == "":
                key = ""

            # add to lists
            if not date == "" and not value == "" and not key == False:
                date_list.append(date)
                value_list.append(value)
                key_list.append(key)
        # end of loop - return appropriate lists
        if len(date_list) == 0:
            print("  --- No valid data found")
        else:
            print("  --- Found " + str(len(date_list)) + " valid data points")
        return [date_list, value_list, key_list]



    def make_image_using_module(self):
        # loag log
        log_data = self.load_log_from_preset(shared_data.graph_data_preset_choice)
        shared_data.list_of_datasets.append(log_data)
        # set graph settings
        ymax = ""
        ymin = ""
        dangercold = ""
        toocold = ""
        toohot = ""
        dangerhot = ""
        size_h, size_v = (7, 12)
        module_name = "line"
        module_name = "graph_" + module_name
        file_name = module_name + "_graph.png"
        graph_path = shared_data.local_graph_path
        #
        if module_name in sys.modules:
            del sys.modules[module_name]
        # import the make_graph function as a module
        exec("from " + module_name + " import make_graph", globals())
        # creaty the graph using the imported module
        extra = ""  #this is temporary testing
        make_graph(shared_data.list_of_datasets, graph_path, ymax, ymin, size_h, size_v, dangerhot, toohot, toocold, dangercold, extra)

        return graph_path

    def display_image(self, path_to_image):
        #img_bmp = wx.StaticBitmap(self, -1, wx.Image(path_to_image, wx.BITMAP_TYPE_ANY).ConvertToBitmap()), 0, wx.ALL, 2)
        bitmap = wx.Bitmap(1, 1)
        bitmap.LoadFile(path_to_image, wx.BITMAP_TYPE_ANY)
        self.img_bmp_box.SetBitmap(bitmap)
        MainApp.window_self.Layout()




    def onToggle(self, event):
        refresh_time_seconds = 1000 * 60
        btnLabel = self.toggleBtn.GetLabel()
        if btnLabel == "Start":
            path_to_image = self.make_image_using_module()
            self.display_image(path_to_image)
            self.timer.Start(refresh_time_seconds)
            self.toggleBtn.SetLabel("Stop")
        else:
            self.timer.Stop()
            self.toggleBtn.SetLabel("Start")

    def update(self, event):
        shared_data.list_of_datasets = []
        path_to_image = self.make_image_using_module()
        self.display_image(path_to_image)
        print (time.ctime(), path_to_image)

class MainFrame ( wx.Frame ):
    def __init__( self, parent ):
        # Settings
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = "Pigrow Data Display", pos = wx.DefaultPosition, style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
        self.Bind(wx.EVT_SIZE, self.resize_window)
        MainApp.display_panel = display_pnl(self)

        # Sizers
        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
        main_sizer.Add(MainApp.display_panel, 0, wx.EXPAND)
        MainApp.window_sizer = wx.BoxSizer(wx.VERTICAL)
        MainApp.window_sizer.Add(main_sizer, 0, wx.EXPAND)
        #MainApp.window_sizer.Fit(self)
        self.SetSizer(MainApp.window_sizer)
        MainApp.window_self = self
        self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
        self.Layout()
        self.Centre( wx.BOTH )

    def resize_window(self, e):
        win_width = e.GetSize()[0]
        win_height = e.GetSize()[1]
        size = wx.Size(win_width, win_height)
        #self.SetMinSize(size)
        MainApp.display_panel.SetMinSize(size)
        try:
            MainApp.window_self.Layout()
        except:
            pass #to avoid the error on first init

class MainApp(MainFrame):
    def __init__(self, parent):
        MainFrame.__init__(self, parent)
        self.Bind(wx.EVT_CLOSE, self.OnClose)

    def OnClose(self, e):
        print(" -- Exiting --")
        sys.exit(0)

def main():
    app = wx.App()
    shared_data()
    window = MainApp(None)
    window.Show(True)
    app.MainLoop()

if __name__ == '__main__':
    try:
        # if run from a desktop icon or something
        os.chdir(os.path.dirname(sys.argv[0]))
    except:
        pass
    main()