// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2018 Thomas Klose & Torsten Schache, Hiperscan GmbH Dresden, Germany
//
//    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/>.


using System;
using System.Collections.Generic;
using Gtk;
using Glade;
using Hiperscan.Unix;
using Gdk;
using GLib;

namespace Hiperscan.Extensions.ApoIdent
{
    public class ModelClassDialogEntry : IComparable<ModelClassDialogEntry>
    {
        public SubstanceCategory Category   {get; set;}
        public string SubstanceName         {get; set;}
        public string ClassName             {get; set;}


        public int CompareTo(ModelClassDialogEntry other)
        {
            if (other == null)
                return 1;

            int lhs = (int) this.Category;
            int rhs = (int) other.Category;

            if (lhs < 3 && rhs > 2)
                return 1;

            if (rhs < 3 && lhs > 2)
                return -1;

            return this.ClassName.CompareTo(other.ClassName);
        }
    }

    public class ModelClassDialog
    {
        [Widget] Gtk.Dialog model_class_dialog      = null;
        [Widget] Gtk.Label advice_label             = null;
        [Widget] Gtk.TreeView model_class_treeview  = null;
        [Widget] Gtk.Button close_button = null;
            
        public ModelClassDialog(SubstanceManagement substance_db, string substance_name, List<string> model_classes)
        {
            Glade.XML gui = new Glade.XML(null, "model_class_dialog.glade", "model_class_dialog", "Hiperscan");
            gui.Autoconnect(this);

            this.model_class_dialog.IconList = ApoIdentStock.FinderIcons;
            this.model_class_dialog.TransientFor = FinderWindow.ParentWindow;

            this.InitSubstanceCategories(18);

            this.model_class_dialog.SetWmclass(Plugin.name.ToLower(), Plugin.name.ToLower());

            this.model_class_dialog.Default = this.close_button;
            this.model_class_dialog.KeyPressEvent += this.OnKeyPressEvent;
            Gtk.ListStore store = new ListStore (typeof(Gdk.Pixbuf),
                                                 typeof(string),
                                                 typeof(string));

            this.model_class_treeview.AppendColumn(Catalog.GetString("Category"), new CellRendererPixbuf(), "pixbuf" , 0);
            this.model_class_treeview.AppendColumn(Catalog.GetString("Substance Name"), new CellRendererText(), "text" , 1);
            this.model_class_treeview.AppendColumn(Catalog.GetString("Classifier"), new CellRendererText(), "text" , 2);

            this.model_class_treeview.Model = store;
            this.model_class_treeview.ButtonPressEvent += this.OnButtonPressEvent;

            List<ModelClassDialogEntry> entries = new List<ModelClassDialogEntry>();

            foreach (string model_class_name in model_classes)
            {
                entries.Add(new ModelClassDialogEntry()
                {
                    Category = substance_db.GetSubstanceCategory(model_class_name, substance_name),
                    SubstanceName = substance_name,
                    ClassName = model_class_name,
                });
            }
  
            entries.Sort();

            foreach (ModelClassDialogEntry class_entry in entries)
            {
                switch (class_entry.Category)
                {
                    case SubstanceCategory.Classifiaction:
                        store.AppendValues(this.YelllowPoint, class_entry.SubstanceName, class_entry.ClassName);
                        break;

                    case SubstanceCategory.UserDefined:
                        store.AppendValues(this.BlackPoint, class_entry.SubstanceName, class_entry.ClassName);
                        break;

                    case SubstanceCategory.NotMeasurable:
                        store.AppendValues(this.RedPoint, class_entry.SubstanceName, class_entry.ClassName);
                        break;

                    case SubstanceCategory.SingleSubstance:
                        store.AppendValues(this.GreenPoint, class_entry.SubstanceName, class_entry.ClassName);
                        break;

                    default:
                        break;
                }
            }

            this.advice_label.Text = String.Format(Catalog.GetString("The substance '{0}' is assigned to " +
                                                                               "several classifiers. Please choose " +
                                                                               "a classifier for continuing substance search."),
                                                                                substance_name);
            

            int width = this.model_class_treeview.SizeRequest().Width + 20;
            if (width > WindowSize.RESOLUTION_WIDTH)
                width = WindowSize.RESOLUTION_WIDTH - 100;

            this.advice_label.WidthRequest = width;
            this.model_class_dialog.HeightRequest = 300;

            this.SelectedClassName = entries[0].ClassName;
            Gtk.TreeIter iter;
            store.GetIterFirst(out iter);
            this.model_class_treeview.Selection.SelectIter(iter);
            this.model_class_treeview.Selection.Changed += this.OnSelectionChanged;

            this.model_class_dialog.IconList = ApoIdentStock.FinderIcons;
            this.model_class_dialog.Run();

            if (this.model_class_dialog != null)
            this.model_class_dialog.Destroy();
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
            Gtk.TreeIter iter;
            this.model_class_treeview.Selection.GetSelected(out iter);
            ListStore store = (ListStore) this.model_class_treeview.Model;
            this.SelectedClassName = (string) store.GetValue(iter, 2);
        }

        [ConnectBefore]
        private void OnButtonPressEvent(object sender, ButtonPressEventArgs e)
        {
            if (e.Event.Button == 1 && e.Event.Type == Gdk.EventType.TwoButtonPress)
                this.model_class_dialog.Destroy();
        }

        [ConnectBefore]
        private void OnKeyPressEvent(object sender, KeyPressEventArgs e)
        {
            if (e.Event.Key == Gdk.Key.Return || e.Event.Key == Gdk.Key.KP_Enter)
                this.model_class_dialog.Destroy();
        }

        private void InitSubstanceCategories(int size)
        {
            this.GreenPoint     = new Pixbuf(null, "green_point.png", size, size);
            this.YelllowPoint   = new Pixbuf(null, "yellow_point.png", size, size);
            this.RedPoint       = new Pixbuf(null, "red_point.png", size, size);
            this.BlackPoint     = new Pixbuf(null, "black_point.png", size, size);
        }

        private Gdk.Pixbuf GreenPoint    {get; set;}
        private Gdk.Pixbuf YelllowPoint  {get; set;}
        private Gdk.Pixbuf RedPoint      {get; set;}
        private Gdk.Pixbuf BlackPoint    {get; set;}

        public string SelectedClassName {get; set;}
    }
}