// 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 System.Collections.Generic;
using System.IO;
using System.Xml;
using Hiperscan.Unix;

namespace Hiperscan.Extensions.ApoIdent
{
    public partial class Configurations
    {
        public class ProfileCollection : Preferences<ProfileCollection>
        {
            public const string PROFILES_TAG = "Profiles";
            private const string CURRENT_PROFILE_ATTRIBUTE = "CurrentProfile";
            private const string IS_DEMO_VERSION_ATTRIBUTE = "IsDemoVersion";
            private const string IS_NEW_ARCHIVE_FORMAT_ATTRIBUTE = "IsNewArchiveFormat";


            public ProfileCollection() : base()
            {
            }

            public ProfileCollection(XmlNode profiles_node) : base(profiles_node)
            {

            }

            protected override void Init(XmlNode parent_node = null)
            {
                this.AllProfiles = new Dictionary<string, ProfilePreferences>();
                this.IsDemoVersion = true;
                this.IsNewArchiveFormat = true;

                base.Init(parent_node);
            }

            protected override void Read(XmlNode parent_node)
            {
                if (parent_node.Attributes[ProfileCollection.IS_NEW_ARCHIVE_FORMAT_ATTRIBUTE] == null)
                    this.IsNewArchiveFormat = false;

                XmlNodeList profile_nodes = parent_node.SelectNodes(ProfilePreferences.PROFILE_TAG);
                if (profile_nodes != null && profile_nodes.Count > 0)
                {
                    foreach (XmlNode profile_node in profile_nodes)
                    {
                        ProfilePreferences profile = new ProfilePreferences(profile_node);

                        if (this.IsNewArchiveFormat == false)
                        {
                            profile.Archive = Path.Combine(profile.Archive, Plugin.name);
                        }

                        this.AllProfiles.Add(profile.Name, profile);
                    }

                    this.IsNewArchiveFormat = true;

                    try
                    {
                        this.Current = this.AllProfiles[parent_node.Attributes[ProfileCollection.CURRENT_PROFILE_ATTRIBUTE].Value];
                    }
                    catch (Exception)
                    {
                        foreach (ProfilePreferences profile in this.AllProfiles.Values)
                        {
                            this.Current = profile;
                            break;
                        }
                    }
                }

                if (parent_node.Attributes[ProfileCollection.IS_DEMO_VERSION_ATTRIBUTE] != null)
                {
                    this.IsDemoVersion = Boolean.Parse(parent_node.Attributes[ProfileCollection.IS_DEMO_VERSION_ATTRIBUTE].Value);
                }
                else
                {
                    if (this.AllProfiles.Count == 0)
                        this.IsDemoVersion = true;
                    if (this.AllProfiles.Count > 1)
                        this.IsDemoVersion = false;
                }
            }

            public override void WriteToXml(XmlDocument doc, XmlNode parent)
            {
                XmlNode profiles_node = doc.CreateElement(ProfileCollection.PROFILES_TAG);
                parent.AppendChild(profiles_node);

                XmlAttribute current_profile_attribute = doc.CreateAttribute(ProfileCollection.CURRENT_PROFILE_ATTRIBUTE);
                current_profile_attribute.Value = this.Current?.Name;
                profiles_node.Attributes.Append(current_profile_attribute);

                XmlAttribute is_demo_version_attribute = doc.CreateAttribute(ProfileCollection.IS_DEMO_VERSION_ATTRIBUTE);
                is_demo_version_attribute.Value = this.IsDemoVersion.ToString();
                profiles_node.Attributes.Append(is_demo_version_attribute);

                XmlAttribute is_new_archive_format_attribute = doc.CreateAttribute(ProfileCollection.IS_NEW_ARCHIVE_FORMAT_ATTRIBUTE);
                is_new_archive_format_attribute.Value = this.IsNewArchiveFormat.ToString();
                profiles_node.Attributes.Append(is_new_archive_format_attribute);

                foreach (ProfilePreferences profile in this.AllProfiles.Values)
                    profile.WriteToXml(doc, profiles_node);
            }

            public override ProfileCollection Clone()
            {
                ProfileCollection tmp = new ProfileCollection();

                foreach (string key in this.AllProfiles.Keys)
                    tmp.AllProfiles.Add(key, this.AllProfiles[key]);

                tmp.Current = this.Current;

                return tmp;
            }

            protected override bool SettingsChanged()
            {
                if (this.Stashed == null)
                    return false;

                if (this.Stashed.Current == null && this.Current != null)
                    return true;

                if (this.Stashed.Current != null && this.Current == null)
                    return true;

                if (this.Stashed.Current != this.Current)
                    return true;

                if (this.Stashed.GetStringValueOfAllProfiles() != this.GetStringValueOfAllProfiles())
                    return true;

                return false;
            }

            private string GetStringValueOfAllProfiles()
            {
                return String.Join("<<>>", this.AllProfiles.Keys);
            }

            public override void Stash()
            {
                foreach (ProfilePreferences item in this.AllProfiles.Values)
                    item.Stash();

                base.Stash();
            }

           public override void Unstash()
            {
                this.Current = null;
                if (String.IsNullOrEmpty(this.NewProfileName) == false)
                {
                    foreach (ProfilePreferences profile in this.AllProfiles.Values)
                    {
                        if (this.NewProfileName == profile.Name)
                        {
                            this.Current = profile;
                            this.NewProfileName = String.Empty;
                            break;
                        }
                    }
                }

                if (String.IsNullOrEmpty(this.NewProfileName) == false)
                    throw new Exception(String.Format(Catalog.GetString("Cannot set to profile name '{0}'. Name does not exist."), this.NewProfileName));
      
                if (this.Current == null && this.Stashed.Current != null)
                {
                    foreach (ProfilePreferences profile in this.AllProfiles.Values)
                    {
                        if (this.Stashed.Current.Name == profile.Name)
                        {
                            this.Current = profile;
                            break;
                        }
                    }
                }

                if (this.Current == null)
                {
                    foreach (ProfilePreferences profile in this.AllProfiles.Values)
                    {
                        this.Current = profile;
                        break;
                    }
                }

                foreach (ProfilePreferences item in this.AllProfiles.Values)
                    item.Unstash();

                base.Unstash();
            }

            public int CurrentIndex(ProfilePreferences profile)
            {
                int index = 0;
                foreach (ProfilePreferences item in this.AllProfiles.Values)
                {
                    if (profile.Name == item?.Name)
                        return index;

                    index++;
                }

                return -1;
            }

            public Dictionary<string, ProfilePreferences> AllProfiles { get; set; }

            public ProfilePreferences Current { get; set; }

            public bool IsDemoVersion { get; set; }
            private bool IsNewArchiveFormat { get; set; }
            public bool NeedCheck { get; set; }

            public string NewProfileName { get; set; } = String.Empty;
        }
    }
}

