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

using Hiperscan.Unix;
using Hiperscan.I18n;
using Hiperscan.Common;
using System.Linq;

namespace Hiperscan.Extensions.ApoIdent
{
    public partial class Preferences
    {
        public void FillPrinterCombo()
        {
            ListStore store = new ListStore(typeof(string));
            CellRendererText text = new CellRendererText();
            this.label_printer_combo.Model = store;
            this.label_printer_combo.PackStart(text, false);
            this.label_printer_combo.SetAttributes(text, "text", 0);

            foreach (string name in this.PrinterNames)
                this.label_printer_combo.AppendText(name);
        }

        public void FillPageSizeCombo()
        {
            this.page_size_combo.Clear();

            if (Config.PrinterSettings.HasPrinter == false)
                return;

            ListStore model = new ListStore(typeof(string));

            CellRendererText paper_name = new CellRendererText();
            this.page_size_combo.PackStart(paper_name, false);
            this.page_size_combo.SetAttributes(paper_name, "text", 0);
            this.page_size_combo.Model = model;

            foreach (System.Drawing.Printing.PaperSize paper_size in this.CurrentPaperSizes.Values)
                model.AppendValues(paper_size.PaperName);
        }

        private void UpdateLabelPrinterSection()
        {
            bool has_printer = this.Config.PrinterSettings.HasPrinter;
            this.label_printer_settings_button.Sensitive = has_printer;
            this.label_printer_test_button.Sensitive = has_printer;
            this.page_size_label.Visible = has_printer;
            this.page_size_combo.Visible = has_printer;
            this.orientation_label.Visible = has_printer;
            this.label_orientation_combo.Visible = has_printer;
            this.label_printer_expander.Visible = has_printer;

            int index = -1;
            index = this.PrinterNames.IndexOf(this.Config.PrinterSettings.PrinterName);
            this.label_printer_combo.Active = index < 0 ? 0 : index;

            index = -1;
            index = new List<string>(this.CurrentPaperSizes.Keys).IndexOf(this.Config.PrinterSettings.PaperSize);
            this.page_size_combo.Active = index < 0 ? 0 : index;

            this.label_orientation_combo.Active = (int)this.Config.PrinterSettings.Orientation;
            this.label_x_offset_spin.Value = this.Config.PrinterSettings.X_IndentMM;
            this.label_y_offset_spin.Value = this.Config.PrinterSettings.Y_IndentMM;
            this.label_scale_factor_spin.Value = this.Config.PrinterSettings.Scale;

            this.label_width_spin.Value = this.Config.PrinterSettings.PaperWidthMM;
            this.label_height_spin.Value = this.Config.PrinterSettings.PaperHeightMM;
        }


   
        private void OnLabelPrinterComboChanged(object o, EventArgs e)
        {
            this.Config.PrinterSettings.PrinterName = this.label_printer_combo.ActiveText;
            this.Config.PrinterSettings.HasPrinter = this.label_printer_combo.Active > 0;
            this.CurrentPaperSizes = LabelPrinter.GetPaperSizes(this.Config.PrinterSettings.PrinterName);

            this.Config.PrinterSettings.PaperSize = this.CurrentPaperSizes.First().Key;
            this.Config.PrinterSettings.PaperWidthMM = this.CurrentPaperSizes[this.Config.PrinterSettings.PaperSize].Width * 25.4 / 100;
            this.Config.PrinterSettings.PaperHeightMM = this.CurrentPaperSizes[this.Config.PrinterSettings.PaperSize].Height * 25.4 / 100;

            this.Config.PrinterSettings.Orientation = PrinterOrientation.Degree_0;
            this.Config.PrinterSettings.Scale = 1.0;
            this.Config.PrinterSettings.X_IndentMM = 0.0;
            this.Config.PrinterSettings.Y_IndentMM = 0.0;

            this.Update(PreferencesUpdateStatus.LabelPrinterChanged);
        }

        private void OnPageSizeComboChanged(object sender, EventArgs e)
        {
            this.Config.PrinterSettings.PaperSize = this.page_size_combo.ActiveText;

            this.Config.PrinterSettings.PaperWidthMM = this.CurrentPaperSizes[this.Config.PrinterSettings.PaperSize].Width * 25.4 / 100;
            this.Config.PrinterSettings.PaperHeightMM = this.CurrentPaperSizes[this.Config.PrinterSettings.PaperSize].Height * 25.4 / 100;

            this.Update(PreferencesUpdateStatus.PageSizeChanged);
        }

        private void OnLabelResetSettingsButtonClicked(object o, EventArgs e)
        {
            this.Config.PrinterSettings.PaperWidthMM = this.CurrentPaperSizes[this.Config.PrinterSettings.PaperSize].Width * 25.4 / 100;
            this.Config.PrinterSettings.PaperHeightMM = this.CurrentPaperSizes[this.Config.PrinterSettings.PaperSize].Height * 25.4 / 100;

            this.Config.PrinterSettings.Orientation = PrinterOrientation.Degree_0;
            this.Config.PrinterSettings.Scale = 1.0;
            this.Config.PrinterSettings.X_IndentMM = 0.0;
            this.Config.PrinterSettings.Y_IndentMM = 0.0;

            this.Update(PreferencesUpdateStatus.ResetPrinterValues);
        }



        private void OnPrinterValueChanged(object sender, EventArgs e)
        {
            this.Config.PrinterSettings.Orientation = (PrinterOrientation)this.label_orientation_combo.Active;
            this.Config.PrinterSettings.PaperWidthMM = this.label_width_spin.Value;
            this.Config.PrinterSettings.PaperHeightMM = this.label_height_spin.Value;
            this.Config.PrinterSettings.X_IndentMM = this.label_x_offset_spin.Value;
            this.Config.PrinterSettings.Y_IndentMM = this.label_y_offset_spin.Value;
            this.Config.PrinterSettings.Scale = this.label_scale_factor_spin.Value;
        }




        private void OnLabelPrinterSettingsButtonClicked(object o, EventArgs e)
        {
            try
            {
                LabelPrinter.PrinterProcessExited -= this.OnLabelPrinterSettingsExited;
                LabelPrinter.PrinterProcessExited += this.OnLabelPrinterSettingsExited;

                Console.WriteLine("Starting printer control...");
                LabelPrinter.StartLabelPrinterSettingsDialog(this.Config.PrinterSettings.PrinterName, this.Config.PrinterSettings.PaperSize);
                Console.WriteLine("Success.");
            }
            catch (Exception ex)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                    Catalog.GetString("Cannot start printer settings control: {0}"),
                    ex.Message);
            }
        }

        private void OnLabelPrinterSettingsExited(object sender, EventArgs e)
        {
            int current_thread = System.Threading.Thread.CurrentThread.ManagedThreadId;
            if (current_thread != this.MainThread)
            {
                Application.Invoke(sender, e, this.OnLabelPrinterSettingsExited);
            }
            else
            {
                try
                {
                    string printer_name = ((string[])sender)[0];
                    string paper_name = ((string[])sender)[1];

                    if (printer_name != this.Config.PrinterSettings.PrinterName)
                        return;

                    if (paper_name != this.Config.PrinterSettings.PaperSize)
                        return;

                    this.Config.PrinterSettings.PaperWidthMM = this.CurrentPaperSizes[this.Config.PrinterSettings.PaperSize].Width * 25.4 / 100;
                    this.Config.PrinterSettings.PaperHeightMM = this.CurrentPaperSizes[this.Config.PrinterSettings.PaperSize].Height * 25.4 / 100;
  
                    this.Update(PreferencesUpdateStatus.PrinterDialogExited);
                }
                catch
                {
                    
                }
            }
        }

        private void OnLabelPrinterTestButtonClicked(object o, EventArgs e)
        {
            Console.WriteLine("Printing test label...");
            try
            {
                LabelPrinter test = new LabelPrinter(this.Config.PrinterSettings);
                test.PrintTestLabel(this.Config.Profiles.Current);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);

                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                    Catalog.GetString("Cannot print test label: {0}"),
                    ex.Message);
            }
        }

        private void OnLabelPrinterHelpButtonClicked(object sender, EventArgs e)
        {
            string path = Path.Combine("Resources", "Pdfs");
            path = Locale.ResourceFileRelativeToAssembly(Assembly.GetExecutingAssembly(), path, "printer_manual.pdf", false);

            string url = "file://" + path.Replace("\\", "/");
            Console.WriteLine("Open URL: " + url);

            try
            {
                if (File.Exists(path) == false)
                    throw new Exception(String.Format(Catalog.GetString("Cannot find file '{0}'."), path));
                System.Diagnostics.Process.Start(url);
            }
            catch (Exception ex)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                    Catalog.GetString("Cannot open ULR '{0}': {1}"),
                    url, ex.Message);
            }
        }



        private List<string> PrinterNames { get; set; } = LabelPrinter.PrinterNames;
        private Dictionary<string, System.Drawing.Printing.PaperSize> CurrentPaperSizes { get; set; }            
    }
}
