// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2017 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 Hiperscan.Unix;
using Hiperscan.ApoIdentCore.Legacy;
using System.Xml;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using Hiperscan.Common.IO;
using System.Text;
using System.Reflection;
using System.ComponentModel;
using Hiperscan.ApoIdentCommon.ApoConfig;
using Hiperscan.ApoIdentCommon.ApoConfig.Enums;
using Hiperscan.AnalysisModule.Identification;
using Hiperscan.ApoIdentCore.SectionManager.Result;
using Hiperscan.AnalysisModule;

namespace Hiperscan.ApoIdentCore.Reporting.ReportData
{
    public partial class ReportInfo
	{
        public static ReportInfo GetTestReportInfo(AnalysisType analysis_type, ProfileSettings profile = null)
        {
            if (profile == null)
            {
                profile = new ProfileSettings();
                profile.Company = Catalog.GetString("Company name");
                 profile.Street = Catalog.GetString("Street name and number");
                profile.Town = Catalog.GetString("City name and ZIP code");
            }

            ReportInfo info = new ReportInfo();

            info.AnalysisType = analysis_type;

            info.Company = profile.Company;
            info.Street = profile.Street;
            info.Town = profile.Town;
            info.ReportCountry = profile.ReportCountry;
            info.BAKMarkingActivated = profile.IsBakMarkingUsable && profile.BakMarking.IsActive;
            info.BAKMarking = BAKMarkingState.Blue | BAKMarkingState.Yellow | BAKMarkingState.Orange;

            info.DefaultName = Catalog.GetString("Selected substance name");
            info.Batch = "ABCDEFG-1234567";
            info.Ppn = "88888888";
            info.Producer = "Snake Oil Ltd.";
            info.ReferenceQuantityValue = 80000.ToString();
            info.ReferenceQuantityUnit = ReferenceQuantityTypes.Pieces;

            info.CorrectionFactor = (0.999).ToString();
            info.Date = DateTime.Now;
            info.TestId = (info.Date.Year % 100).ToString() + info.Date.ToString("MMdd-HHmmss");
            info.HasCustomerResult = false;

            info.ExpireDate = DateTime.Now.AddDays(180);
            info.Comment = Catalog.GetString("Comment");

            CannabisResult cannabis_result = CannabisResult.GetTestInstance();
            info.CannabisClassification = cannabis_result.GetCannabisClassification();
            info.THCInput = "10,0";
            info.CBDInput = "10,0";
            info.Variety = Catalog.GetString("Variety");
            info.CannabisResultIsTrustable = cannabis_result.IsTrustable;

            return info;
        }
        public static void Write(ReportInfo info, string xml_filename)
        {
            try
            {
                xml_filename = Path.GetFullPath(xml_filename);
                string directory = Path.GetDirectoryName(xml_filename);
                FileIO.CreateDirectoryIfNotExists(directory, FileAttributes.Hidden);

                XmlObject writer = new XmlObject();
                writer.Write(info, xml_filename);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error while writing QueryMetadata; {0}", ex);
            }
        }

        public static ReportInfo Read(string xml_filename)
        {
            xml_filename = Path.GetFullPath(xml_filename);

            XmlObject xmlreader = new XmlObject();
            xmlreader.SerializationCulturePropertyName = "SerializedCulture";

            ReportInfo info = (ReportInfo)xmlreader.Deserialize(xml_filename, typeof(ReportInfo));

            string file_name = Path.GetFileNameWithoutExtension(xml_filename);
            string parent_dir = Path.GetDirectoryName(Path.GetDirectoryName(xml_filename));
            info.XmlFileFulleName = xml_filename;
            info.PdfFileFullName = Path.Combine(parent_dir, file_name + ".pdf");
            if (info.IsMeasurable == true)
                info.CsvFilFullName = Path.Combine(parent_dir, file_name + ".csv");

            return info;
        }

        public static void ConvertToMetaData2_0(AppControl control)
        {
            try
            {
                List<string> directories = new List<string>();

                foreach (ProfileSettings profile in control.ProfileManager.AllProfiles.Values)
                {
                    if (false == FileIO.ExistsDirectory(profile.Archive))
                        continue;

                    ReportInfo.ConvertToMetaData2_0(profile.Archive);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error while converting spectra to query meta data: {0}", ex.Message);
            }
        }

        private static void ConvertToMetaData2_0(string directory)
        {
            Regex folder_pattern = new Regex(@"^20\d\d$");

            foreach (string sub_dir in FileIO.GetDirectories(directory))
            {
                if (folder_pattern.Match(Path.GetFileName(sub_dir)).Success == false)
                    continue;

                string query_dir = Path.Combine(sub_dir, ProfileSettings.QUERY_DIR);
                if (false == FileIO.ExistsDirectory(query_dir))
                    continue;

                foreach (string xml_file in FileIO.GetFiles(query_dir, "*.xml"))
                {
                    try
                    {
                        ReportInfo info = ReportInfo.ReadOldVersion(xml_file);
                        if (info == null)
                            continue;

                        info.ReportInfoVersion = "1.0";

                        ReportInfo.Write(info, xml_file);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Error while converting report info: File = {0}, message = {1}",
                                          xml_file, ex.Message);
                    }
                }
            }
        }

        private static ReportInfo ReadOldVersion(string file_name)
        {
            ReportInfo query = new ReportInfo();

            using (StreamReader sr = new StreamReader(file_name, Encoding.UTF8))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(sr);

                bool found_customer_result = false;
                bool found_country = false;
                bool found_is_measurable = false;


                XmlNode root = doc.GetElementsByTagName(ReportInfo.QUERY_TAG)[0];
                if (root == null)
                    return null;

                foreach (XmlElement element in root.ChildNodes)
                {
                    if (element.Name == "Specimen")
                    {
                        query.DefaultName = element.InnerText;
                        continue;
                    }

                    if (element.Name == "Latin")
                    {
                        query.LatinName = element.InnerText;
                        continue;
                    }

                    foreach (PropertyInfo property in query.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
                    {
                        if (property.Name == "Label" || property.Name == "FileName")
                            continue;

                        if (property.Name == element.Name)
                        {
                            TypeConverter converter = TypeDescriptor.GetConverter(property.PropertyType);
                            object value = converter.ConvertFromInvariantString(element.InnerText);
                            property.SetValue(query, value, null);

                            switch (property.Name)
                            {

                                case "CustomerResult":
                                    found_customer_result = true;
                                    break;

                                case "Country":
                                    found_country = true;
                                    break;

                                case "IsMeasurable":
                                    found_is_measurable = true;
                                    break;

                                default:
                                    break;
                            }
                        }
                    }
                }

                if (found_customer_result == false)
                    query.CustomerResult = query.IsMatch;

                if (found_country == false)
                    query.ReportCountry = ReportCountryTypes.Germany;

                if (found_is_measurable == false)
                {
                    try
                    {
                        string spectrum_file = Path.GetFileNameWithoutExtension(file_name) + ".csv";
                        string path = new FileInfo(file_name).Directory.Parent.FullName;
                        query.IsMeasurable = FileIO.ExistsFile(Path.Combine(path, spectrum_file));
                    }
                    catch (Exception) { }
                }
            }

            return query;
        }

        public static IDetailPlot DetailPlot { get; set; }
    }
}
