// 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.IO;
using Gtk;

using Hiperscan.FileIO;
using Hiperscan.Spectroscopy;
using Hiperscan.PdfLib;
using Hiperscan.Unix;
using System.Collections.Generic;

namespace Hiperscan.Extensions.ApoIdent
{
	
	public partial class FinderWindow
	{
        private void CreateReport()
		{
            if (string.IsNullOrEmpty(FilesAndDirs.Archive) == true || Directory.Exists(this.Config.Profiles.Current.Archive) == false)
                throw new Exception(Catalog.GetString("Archive directory does not exist or permission is denied."));

            if (Directory.Exists(FilesAndDirs.ArchiveYearDir) == false)
                Directory.CreateDirectory(FilesAndDirs.ArchiveYearDir);

            this.UpdateEntryCompletion();

  
            ReportInfo old_info = null;
            if (this.CurrentReport != null)
                old_info = this.ReportInfo;

            this.ReportInfo = new ReportInfo(this);

            if (old_info != null)
			{
                try { File.Delete(old_info.PdfFileFullName); }catch(Exception){};
                try { File.Delete(old_info.XmlFileFulleName); }catch (Exception) { };
                if (this.ReportInfo.IsMeasurable == true)
                    try { File.Delete(old_info.CsvFilFullName); }catch(Exception){};
			}

            this.CurrentReport = this.SelectReport(this.ReportInfo);

            ReportInfo.Write(this.ReportInfo, FilesAndDirs.ProtocolXmlFileName(this.ReportInfo));
            if (this.ReportInfo.IsMeasurable == true)
                CSV.Write(this.ReportInfo.Spectrum, FilesAndDirs.ProtocolCsvFileName(this.ReportInfo), this.ReportInfo.Culture);
            
			this.ExchangeDataImportFinishedDialog();
            this.DetailSectionState.Set(DetailSectionStates.ReportNotSaved, false);
		}

        private Report.Generic SelectReport(ReportInfo report_info)
        {
            Report.Generic report = null;

            switch(report_info.ReportCountry)
            {

                case ReportCountryType.Austria:
                    report = new Report.Austria(report_info);
                    break;

                case ReportCountryType.Germany:
                    report = new Report.Germany(report_info);
                    break;

                case ReportCountryType.Switzerland:
                    report = new Report.Switzerland(report_info);
                    break;

                case ReportCountryType.GreatBritain:
                    report = new Report.GreatBritain(report_info);
                    break;

                default:
                    throw new NotImplementedException("Unknown report country: " + report_info.ReportCountry);

            }

            return report;
        }

		private void ExchangeDataImportFinishedDialog()
		{
            if (this.SubstanceManagement.ProtocolCompletion == ProtocolAutoCompletionType.ThirdParty)
			{
                this.Config.Profiles.Current.ExchangeData.ExportFile(this.ReportInfo);

				Gtk.MessageDialog mdlg = new MessageDialog(this.finder_window,
					DialogFlags.Modal,
					MessageType.Info,
					ButtonsType.Ok,
					Catalog.GetString("The data import for 'Dr-Lennartz' is finished. " +
						"You can still do some changes in the fields 'comment' or 'additional test' " +
						"before you integrate the protocol in tge 'Dr. Lennartz'-application. "));

                mdlg.IconList = ApoIdentStock.FinderIcons;
				mdlg.Run();
				mdlg.Destroy();
			}
		}
			
		
		private bool SaveReport(bool last_chance)
		{
            if (this.DetailSectionState.IsSet(DetailSectionStates.ReportNotSaved) == true)
			{
                Preferences.CheckForDemoVersion(this.finder_window, this.Config);
				
				try
				{
					//TODO 1.3 better handling of SaveReport()
					// that means, if this method returns false, then all changes has to be reseted!!!!
					/*
					if (this.pzn_hregexentry.IsTextValid == false)
					{
						string message = Catalog.GetString("Error saving file: The input in field 'PZN' is not correct.");
						this.host.ShowInfoMessage(this.finder_window, message);
						this.Update(FinderUpdateState.ReportSavedFailed, message);
						GLib.Timeout.Add(5000, this.SaveTimer);
						return false;
					}
					*/

					this.CreateReport();

                    if (last_chance == false)
                    {
                        this.Update(FinderUpdateState.ReportSaved);
                        GLib.Timeout.Add(5000, this.SaveTimer);
                    }
				}
				catch(PdfLayoutException ex)
				{
					string message = String.Format(Catalog.GetString("Error creating file: {0}"), ex.Message);
					message += Catalog.GetString("\n\nThe most common reason for this error is a too long input in the field \"additional test\". " +
                            "Please check this input.");
					message += ServiceForRepeatedError;
					this.host.ShowInfoMessage(this.finder_window, message);
					this.Update(FinderUpdateState.ReportSavedFailed, message);
					GLib.Timeout.Add(5000, this.SaveTimer);
					return false;
				}
				catch(Exception ex)
				{
					Console.WriteLine("Error saving report: {0}", ex.ToString());
					string message = String.Format(Catalog.GetString("Error saving file: {0}"), ex.Message);
					message += Catalog.GetString("\n\n" +
					                             "Please check if the archive directory exists and that you can write data in this archive.");
					message += ServiceForRepeatedError;
					this.host.ShowInfoMessage(this.finder_window, message);
					this.Update(FinderUpdateState.ReportSavedFailed, message);
					GLib.Timeout.Add(5000, this.SaveTimer);
					return false;
				}
			}
			return true;
		}
		
		private bool SaveTimer()
		{
			this.Update(FinderUpdateState.AfterReportSaving);
			return false;
		}

		private bool RemindSave()
		{
            if (this.DetailSectionState.IsSet(DetailSectionStates.SaveReport) == false)
				return true;
			
			MessageDialog mdlg = new MessageDialog(
				this.finder_window,
				DialogFlags.Modal,
				MessageType.Warning,
				ButtonsType.YesNo,
				Catalog.GetString("Last changes of the report has not been saved yet. Do you want to save them now?"));

			mdlg.Title = Catalog.GetString("Reminding Saving");
            mdlg.IconList = ApoIdentStock.FinderIcons;
			ResponseType answer = (ResponseType) mdlg.Run();
			mdlg.Destroy();

			if (answer == ResponseType.Yes)
			{
				if (this.SaveReport(true) == false)
				{

					Gtk.MessageDialog dialog = new Gtk.MessageDialog( this.finder_window, Gtk.DialogFlags.Modal,
                                                                     Gtk.MessageType.Warning, Gtk.ButtonsType.YesNo,
					                          	Catalog.GetString("The report couldn't be saved. Do you want try saving again?"));

                    dialog.IconList = ApoIdentStock.FinderIcons;

					if ((Gtk.ResponseType)dialog.Run() == Gtk.ResponseType.No)
					{
                        this.DetailSectionState.Set(DetailSectionStates.ReportNotSaved, false);
						this.Update(FinderUpdateState.ReportChanged);
						dialog.Destroy();
						return true;
					}
					else
					{
						dialog.Destroy();
						this.Update(FinderUpdateState.ReportChanged);
						return false;
					}
				}
				else
				{
                    this.DetailSectionState.Set(DetailSectionStates.ReportNotSaved, false);
					this.Update(FinderUpdateState.ReportChanged);
				}
			}

			return true;
		}

        internal void OnSaveReportButtonClicked(object o, EventArgs e)
        {
            bool success = true;
            if (this.DetailSectionState.IsSet(DetailSectionStates.ReportNotSaved) == true)
            {
                success = this.SaveReport(false);

                if (success == true)
                    this.Update(FinderUpdateState.ReportChanged);
            }
        }

        internal void OnShowReportButtonClicked(object o, EventArgs e)
        {
            bool success = true;
            if (this.DetailSectionState.IsSet(DetailSectionStates.ReportNotSaved) == true)
            {
                success = this.SaveReport(false);
                if (success == true)
                    this.Update(FinderUpdateState.ReportChanged);
            }

            if (success == true)
            {
                try
                {
                    this.FinderAnimation.ResetErrorsWithoutMisIdentification();
                    this.CurrentReport.Show();
                }
                catch (Exception ex)
                {
                    string message = String.Format(Catalog.GetString("Cannot show report: {0}"), ex.Message);
                    message += ServiceForRepeatedError;
                    this.host.ShowInfoMessage(this.finder_window, message);
                    this.FinderAnimation.SetError(AnimationErrorType.ShowReportFailed, message);
                }
            }
        }

        internal void OnPrintReportButtonClicked(object o, EventArgs e)
        {
            bool success = true;
            if (this.DetailSectionState.IsSet(DetailSectionStates.ReportNotSaved) == true)
            {
                success = this.SaveReport(false);
                if (success == true)
                    this.Update(FinderUpdateState.ReportChanged);
            }

            if (success == true)
            {
                try
                {
                    this.FinderAnimation.ResetErrorsWithoutMisIdentification();
                    this.CurrentReport.Print();
                }
                catch (Exception ex)
                {
                    string message = String.Format(Catalog.GetString("Cannot print report: {0}"), ex.Message);
                    message += Catalog.GetString("\nPlease check the printer setting on your computer.");
                    message += ServiceForRepeatedError;
                    this.host.ShowInfoMessage(this.finder_window, message);
                    this.FinderAnimation.SetError(AnimationErrorType.PrintigFailed, message);
                }
            }
        }

        internal void OnPrintLabelButtonClicked(object o, EventArgs e)
        {

            bool success = true;
            if (this.DetailSectionState.IsSet(DetailSectionStates.ReportNotSaved) == true)
            {
                success = this.SaveReport(false);
                if (success == true)
                    this.Update(FinderUpdateState.ReportChanged);
            }

            if (success == true)
            {
                try
                {
                    this.FinderAnimation.ResetErrorsWithoutMisIdentification();
                    LabelPrinter printer = new LabelPrinter(this.Config.PrinterSettings);
                    printer.Print(this.ReportInfo);
                }
                catch (Exception ex)
                {
                    string message = String.Format(Catalog.GetString("Cannot print label: {0}"), ex.Message);
                    message += Catalog.GetString("\nPlease check the printer settings on your computer " +
                                                 "or check the label printer settings in the preferences dialog.");
                    message += ServiceForRepeatedError;
                    this.host.ShowInfoMessage(this.finder_window, message);
                    this.FinderAnimation.SetError(AnimationErrorType.LabelPrintigFailed, message);
                }
            }
        }

		public ReportInfo ReportInfo	{get; private set;}
		public string PdfFile			{get; private set;}
		
		public bool CreateNotMeasurableReport		{get; private set;}
        public DateTime NotMeasurableCreationDate	{get; set;}
	}	
	
}
