#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016  Carlos Henrique Silva <carlosqsilva@outlook.com>
#
# This program 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.
#
# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk

import matplotlib as mpl
mpl.use('GTK3Cairo')
# import matplotlib.pyplot as plt
# plt.style.use('dark_background')

from matplotlib.backends.backend_gtk3cairo import FigureCanvasGTK3Cairo as FigureCanvas

import sys
import pandas as pd
from io import StringIO
from pyspc import *

control_charts = {"Cusum": [cusum],
                  "Ewma": [ewma],
                  "Sbar": [xbar_sbar, sbar],
                  "Rbar": [xbar_rbar, rbar],
                  "T-Square Single": [Tsquare_single],
                  "T-Square": [Tsquare],
                  "MEWMA": [mewma],
                  "Moving Range": [xmr, mr],
                  "C Chart": [c],
                  "NP Chart": [np],
                  "P Chart": [p],
                  "U Chart": [u],
                  "I-MR-R": [imrx, imrmr, imrr],
                  "I-MR-S": [imrx, imrmr, imrstd]}


class FileDialog(Gtk.Dialog):

    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "File Dialog", parent, 0,
                            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                             Gtk.STOCK_OK, Gtk.ResponseType.OK))
        self.set_default_size(500, 550)
        box = self.get_content_area()

        self.verticalbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3)
        box.add(self.verticalbox)

        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)

        from_file = Gtk.Button("From File")
        from_file.connect("clicked", self.on_file)
        from_clipboard = Gtk.Button("Clipboard")
        from_clipboard.connect("clicked", self.on_clipboard)

        hbox1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, homogeneous=True)
        hbox1.pack_start(from_file, True, True, 0)
        hbox1.pack_start(from_clipboard, True, True, 0)
        self.verticalbox.pack_start(hbox1, False, False, 0)

        # Just holding the Place for real treeview widget
        self.scrollable_treelist = Gtk.Label()
        self.verticalbox.pack_start(self.scrollable_treelist, True, True, 0)

        self.show_all()

    def add_treeview(self):
        num_columns = [float for x in range(len(self.data.columns))]

        liststore = Gtk.ListStore(*num_columns)
        for ref in self.data.values.tolist():
            liststore.append(ref)

        treeview = Gtk.TreeView.new_with_model(liststore)
        for i, column_title in enumerate(self.data.columns):
            renderer = Gtk.CellRendererText()
            column = Gtk.TreeViewColumn(column_title, renderer, text=i)
            treeview.append_column(column)

        self.scrollable_treelist = Gtk.ScrolledWindow()
        self.scrollable_treelist.add(treeview)
        self.scrollable_treelist.set_vexpand(True)
        self.scrollable_treelist.set_hexpand(True)
        self.verticalbox.pack_start(self.scrollable_treelist, True, True, 0)
        self.verticalbox.show_all()

    def on_file(self, button):

        dialog = Gtk.FileChooserDialog("Please choose a file", self,
                                       Gtk.FileChooserAction.OPEN,
                                       (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                                        Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
        filter_csv = Gtk.FileFilter()
        filter_csv.set_name("CSV Files")
        filter_csv.add_pattern("*.csv")
        dialog.add_filter(filter_csv)

        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            path = dialog.get_filename()
            self.data = pd.read_csv(path)
            self.verticalbox.remove(self.scrollable_treelist)
            self.add_treeview()

        dialog.destroy()

    def on_clipboard(self, button):
        kwargs = dict()
        text = self.clipboard.wait_for_text()
        lines = text[:10000].split('\n')[:-1][:10]

        counts = set([x.lstrip().count('\t') for x in lines])
        if len(lines) > 1 and len(counts) == 1 and counts.pop() != 0:
            kwargs['sep'] = '\t'

        if kwargs.get('sep') is None and kwargs.get('delim_whitespace') is None:
            kwargs['sep'] = '\s+'

        try:
            self.data = pd.read_table(StringIO(text), **kwargs)
        except:
            print("Unexpected Error: ", sys.exc_info())
        else:
            self.verticalbox.remove(self.scrollable_treelist)
            self.add_treeview()


class main(Gtk.Window):

    def __init__(self, *args):
        super(main, self).__init__(*args)

        self.data = []
        self.graph = None
        self.charts = None

        self.win = Gtk.Window()
        self.set_border_width(4)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_title("PySpc : Statistical Process Control Charts for Humans")
        self.set_default_size(480, 600)
        self.connect("delete-event", Gtk.main_quit)

        self.buildui()

    def buildui(self):
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        toolbar = Gtk.Toolbar()
        toolbar.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR)
        vbox.pack_start(toolbar, False, False, 0)
        self.add(vbox)

        open_file = Gtk.ToolButton()
        open_file.set_tooltip_text("Open file contain data")
        open_file.set_icon_name("bookmark-new-symbolic")
        open_file.connect("clicked", self.on_file_clicked)
        toolbar.insert(open_file, 0)

        toolbar.insert(Gtk.SeparatorToolItem(), 1)

        charts_store = Gtk.ListStore(str)
        charts = ["Cusum", "Ewma", "Sbar", "Rbar", "T-Square Single", "T-Square", "MEWMA", "C Chart",
                  "NP Chart", "P Chart", "U Chart", "Moving Range", "I-MR-R", "I-MR-S"]
        for chart in charts:
            charts_store.append([chart])

        charts_combo = Gtk.ComboBox.new_with_model(charts_store)
        charts_combo.connect("changed", self.on_charts_combo_changed)
        renderer_text = Gtk.CellRendererText()
        charts_combo.pack_start(renderer_text, True)
        charts_combo.add_attribute(renderer_text, "text", 0)
        tool_combo_container = Gtk.ToolItem()
        tool_combo_container.add(charts_combo)
        tool_combo_container.set_tooltip_text("Choose the right control chart for the data you opened")
        tool_label_container = Gtk.ToolItem()
        tool_label_container.add(Gtk.Label("Control Chart: "))
        toolbar.insert(tool_label_container, 2)
        toolbar.insert(tool_combo_container, 3)

        toolbar.insert(Gtk.SeparatorToolItem(), 4)

        plot_chart = Gtk.ToolButton()
        plot_chart.set_tooltip_text("Plot the control chart selected")
        plot_chart.connect("clicked", self.on_plot_clicked)
        plot_chart.set_icon_name("image-filter-symbolic")
        toolbar.insert(plot_chart, 5)

        toolbar.insert(Gtk.SeparatorToolItem(), 6)

        save_chart = Gtk.ToolButton()
        save_chart.set_tooltip_text("Save the control chart image")
        save_chart.connect("clicked", self.on_save_clicked)
        save_chart.set_icon_name("insert-image-symbolic")
        toolbar.insert(save_chart, 7)

        stack = Gtk.Stack()
        stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
        stack.set_transition_duration(800)

        self.plotcanvas = Gtk.Label("Plot Goes Here")
        self.canvas_box = Gtk.Box(Gtk.Orientation.VERTICAL)
        self.canvas_box.pack_start(self.plotcanvas, True, True, 0)
        stack.add_titled(self.canvas_box, "canvas", "Control Charts")

        self.summary = Gtk.ListBox()
        self.summary_box = Gtk.Box(Gtk.Orientation.VERTICAL)
        self.summary_box.pack_start(self.summary, True, True, 0)
        stack.add_titled(self.summary_box, "summary", "Summary")

        stack_switcher = Gtk.StackSwitcher(homogeneous=True)
        stack_switcher.set_stack(stack)
        vbox.pack_start(stack_switcher, False, False, 0)
        vbox.pack_start(stack, True, True, 0)

    def on_charts_combo_changed(self, combo):
        tree_iter = combo.get_active()
        if tree_iter is not None:
            model = combo.get_model()
            chart = model[tree_iter][0]
            self.charts = chart

    def on_plot_clicked(self, widget):
        self.canvas_box.remove(self.plotcanvas)
        graph = spc(self.data) + rules()
        for chart in control_charts[self.charts]:
            graph = graph + chart()
        self.graph = graph
        self.graph.make()

        self.plotcanvas = FigureCanvas(self.graph.fig)
        self.canvas_box.pack_start(self.plotcanvas, True, True, 0)
        self.canvas_box.show_all()
        # self.vbox.show_all()

    def on_file_clicked(self, widget):
        # dialog = Gtk.FileChooserDialog("Please choose a file", self,
        #                                Gtk.FileChooserAction.OPEN,
        #                                (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
        #                                 Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
        # response = dialog.run()
        # if response == Gtk.ResponseType.OK:
        #     path = dialog.get_filename()
        #     # self.open_file.set_label("File Selected: %s" % os.path.basename(path))
        #     self.data = pd.read_csv(path)

        # elif response == Gtk.ResponseType.CANCEL:
        #     print("Cancel clicked")

        # dialog.destroy()
        dialog = FileDialog(self)
        # dialog.show_all()
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            self.data = dialog.data
        dialog.destroy()

    def on_save_clicked(self, widget):
        dialog = Gtk.FileChooserDialog("Please choose a filename to save", self,
                                       Gtk.FileChooserAction.SAVE,
                                       (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                                        Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
        dialog.set_current_name("Untitled.png")
        dialog.set_do_overwrite_confirmation(True)
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            self.graph.save(dialog.get_filename(), dpi=600)

        dialog.destroy()


if __name__ == '__main__':
    app = main()
    app.show_all()
    Gtk.main()