// 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;

namespace Hiperscan.Extensions.ApoIdent
{

	public class Profiles : Dictionary<string, Profile>
	{
		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 event EventHandler ProfileSettingsChanged = null;
		public event EventHandler ProfileChanged = null;

		public Profiles()
		{
			this.IsDemoVersion = true;
			this.IsNewArchiveFormat = true;
		}

		public Profiles(XmlNode profiles_node) : this()
		{
			if (profiles_node.Attributes[Profiles.IS_NEW_ARCHIVE_FORMAT_ATTRIBUTE] == null)
				this.IsNewArchiveFormat = false;

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

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

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

				this.IsNewArchiveFormat = true;

				try
				{
					this.Current = this[profiles_node.Attributes[Profiles.CURRENT_PROFILE_ATTRIBUTE].Value];
				}
				catch (Exception)
				{
					foreach (Profile profile in this.Values)
					{
						this.Current = profile;
						break;
					}
				}
			}

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

            if (this.IsDemoVersion == true && this.Count == 1)
            {
                if (this.IsDemoVersion == true)
                {
                    if (this.Current.Company != "Unknown organisation" && this.Current.Company != "unbekannte Organisation")
                        this.IsDemoVersion = false;
                }
            }
		}

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

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

			XmlAttribute is_demo_version_attribute = doc.CreateAttribute(Profiles.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(Profiles.IS_NEW_ARCHIVE_FORMAT_ATTRIBUTE);
			is_new_archive_format_attribute.Value = this.IsNewArchiveFormat.ToString();
			profiles_node.Attributes.Append(is_new_archive_format_attribute);

			foreach (Profile profile in this.Values)
				profile.WriteToXml(doc, profiles_node);
		}
      
		public int CurrentIndex(Profile profile)
		{
			int index = 0;
			foreach (Profile item in this.Values)
			{
				if (profile.Name == item?.Name)
					return index;

				index++;
			}

			return -1;
		}

		public void Stash()
		{
			this.Stashed = this.Current?.Clone();
		}

		public void Unstash(bool check_settings_changes)
		{
			if (check_settings_changes == false)
			{
				this.Current = this.Stashed;
				return;
			}

			this.Current = null;       
			foreach (Profile profile in this.Values)
            {
				if (this.Stashed == null)                    
					break;
				
				if (this.Stashed.Name == profile.Name)
				{
					this.Current = profile;
					break;
				}	
            }

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

				if (this.ProfileChanged != null)
					this.ProfileChanged(this, EventArgs.Empty);				
			}
			else
			{
				if (this.ProfileSettingsChanged != null)
					this.ProfileSettingsChanged(this, EventArgs.Empty);
			}

			this.Stashed = null;
		}

		public Profile Stashed { get; set; }
		public Profile Current { get; set; }
        
		public bool IsDemoVersion           { get; set; }
		private bool IsNewArchiveFormat     { get; set; }    
		public bool NeedCheck               { get; set; }
	}
}

