// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2014 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.IO;
using System.Reflection;

using Gtk;

using Hiperscan.Common.I18n;
using Hiperscan.Unix;
using Hiperscan.ApoIdentCore;
using Hiperscan.ApoIdentCore.Reporting.RankingList;
using Hiperscan.AnalysisModule;
using Hiperscan.AnalysisModule.Identification.Result;
using Hiperscan.ApoIdentCommon.ApoConfig.IO;

namespace Hiperscan.Extensions.ApoIdent
{
    public class ResultListTv : Gtk.TreeView
    {
        public delegate void DoubleClickedHandler(ResultListTv tv);
        public event         DoubleClickedHandler DoubleClicked;


        public ResultListTv() : base() {}

        protected override bool OnButtonPressEvent(Gdk.EventButton e)
        {
            if ((e.Button == 1) && (e.Type == Gdk.EventType.TwoButtonPress) && (this.DoubleClicked != null))
                this.DoubleClicked(this);

            return base.OnButtonPressEvent(e);
        }
    }

    public class ResultListDialog
    {
        public static ResultListDialog Run(Gtk.Window parent, AppControl control)
        {
            return new ResultListDialog(parent, control);
        }

        private ResultListDialog(Gtk.Window parent, AppControl control)
        {
            this.FileSystem = control.FileSystem;

            Dialog dialog = new Dialog(Catalog.GetString("Identification details"),
                parent, DialogFlags.Modal);

            dialog.AddButton(Stock.Help, ResponseType.Help);
            dialog.AddButton(Catalog.GetString("Show as PDF"), ResponseType.Yes);
            dialog.AddButton(Stock.Close, ResponseType.Close);

            dialog.HasSeparator  = true;
            dialog.HeightRequest = 400;



            ResultListTv tv = new ResultListTv();
            tv.Selection.Mode = SelectionMode.Single;

            ListStore result_list = new ListStore (typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(int), typeof(string));

            CellRendererText ellipsized_cell_text = new CellRendererText();
            ellipsized_cell_text.Ellipsize = Pango.EllipsizeMode.End;

            tv.RulesHint = true;
            tv.AppendColumn(Catalog.GetString("Ranking"),        new CellRendererText(), "text", 0, "foreground", 9);
            tv.AppendColumn(Catalog.GetString("Classification"), ellipsized_cell_text,   "text", 1, "foreground", 9);
            tv.AppendColumn(Catalog.GetString("Sample ID"),      new CellRendererText(), "text", 2, "foreground", 9);
            tv.AppendColumn(Catalog.GetString("Significance"),   new CellRendererText(), "text", 3, "foreground", 9);
            tv.AppendColumn(Catalog.GetString("Confidence"),     new CellRendererText(), "text", 4, "foreground", 9);
            tv.AppendColumn(Catalog.GetString("Correlation"),    new CellRendererText(), "text", 5, "foreground", 9);
            tv.AppendColumn(Catalog.GetString("Distance"),       new CellRendererText(), "text", 6, "foreground", 9);
            tv.AppendColumn(Catalog.GetString("Rating"),         new CellRendererText(), "text", 7, "foreground", 9);

            Gtk.TreeViewColumn classification_column = tv.Columns[1];
            classification_column.Expand = true;
            classification_column.MinWidth = 250;

            string first_rating = (control.ResultManager. IdentificationResult.Rating * 100).ToString("f2") + "%";
            bool draw_green = false;
            bool show_number = false;

            if (control.ResultManager.IdentificationIsTruePositive == true)
                draw_green = true;

            if (control.ResultManager.IdentificationResult.ClassificationMatch == true)
                show_number = true;

            for (int ranking = 0; ranking < control.ResultManager.IdentificationResult.PcaMatches.Count; ++ranking)
            {
                string color = "red";
                string rating = 0.ToString("f2") + "%";

                if (ranking == 0)
                {
                    if (draw_green)
                        color = "darkgreen";

                    if (show_number)
                        rating = first_rating;
                }

                NormalizedPcaMatch match = control.ResultManager.IdentificationResult.PcaMatches[ranking];
                result_list.AppendValues((ranking+1).ToString(),
                                         match.EvaluationClassificationName,
                                         match.SampleId,
                                         match.Significance.ToString("f4"),
                                         match.Confidence.ToString("f4"),
                                         match.Correlation.ToString("f4"),
                                         match.Distance.ToString("f1"),
                                         rating,
                                         ranking,
                                         color);
            }
            
            tv.Model = result_list;

            ScrolledWindow sw = new ScrolledWindow();
            sw.HscrollbarPolicy = PolicyType.Never;
            sw.VscrollbarPolicy = PolicyType.Automatic;
            sw.Add(tv);
            
            dialog.VBox.PackStart(sw);
            sw.ShowAll();
            
            dialog.ActionArea.Children[0].HasFocus = true;
            dialog.IconList = ApoIdentStock.FinderIcons;

            GuiDesigner.SetSchema(dialog);

            for (;;)
            {
                ResponseType response = (ResponseType) dialog.Run();

                if (response == ResponseType.Help)
                {
                    
                    this.ShowHelpPDF("result_list.pdf", dialog);
                    continue;
                }

                if (response == ResponseType.Yes)
                {
                    this.ShowRankingListPdf(control, dialog);
                    continue;
                }
                break;
            }

            dialog.Destroy();
            this.DeletePdfRankingList(true);
        }

        private void ShowRankingListPdf(AppControl control, Gtk.Window parent)
        {
            try
            {
                this.DeletePdfRankingList(true);

                this.PdfRankingList = new RankingListPdf(control.ResultManager.IdentificationResult,
                                                  control.MeasuringManager.GetMeasurmentId(),
                                                  ApoIdentInfo.FullVersion,
                                                  control.SubstanceManager.GetServerInfo(AnalysisType.Identification).Version.ModuleVersion);
                this.PdfRankingList.Show();
            }
            catch(Exception ex)
            { 
                string message = String.Format(Catalog.GetString("Cannot show pdf for ranking list: {0}"),
                                              ex.Message);

                MessageDialog mdlg = new MessageDialog(parent,
                                                       DialogFlags.Modal,
                                                       Gtk.MessageType.Error,
                                                       ButtonsType.Ok,
                                                       message)
                {
                    IconList = ApoIdentStock.FinderIcons
                };
                mdlg.Run();
                mdlg.Destroy();
                Console.WriteLine("Erro while showing ranking list pdf for result list: {0}.", ex);
            }
        }

        private void ShowHelpPDF(string file_name, Gtk.Window parent)
        {
            try
            {
                this.FileSystem.OpenPdf(file_name);
            }
            catch (Exception ex)
            {
                string message = String.Format(Catalog.GetString("Cannot open ULR: {0}"),
                                              ex.Message);

                MessageDialog mdlg = new MessageDialog(parent,
                                                       DialogFlags.Modal,
                                                       Gtk.MessageType.Error,
                                                       ButtonsType.Ok,
                                                       message)
                {
                    IconList = ApoIdentStock.FinderIcons
                };
                mdlg.Run();
                mdlg.Destroy();  
                Console.WriteLine("Erro while showing help for result list: {0}.", ex);
            }
        }

        private void DeletePdfRankingList(bool surpress_exception)
        {
            try
            {
                if (this.PdfRankingList != null)
                    this.PdfRankingList.Delete();
            }
            catch(Exception)
            {
                if (surpress_exception == false)
                    throw;
            }
        }

        private RankingListPdf PdfRankingList { get; set; }
        private ApoIdentFileSystem FileSystem { get; set; }
    }
}
