using RelhaxModpack.Database;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RelhaxModpack.Database
{
    /// <summary>
    /// A structure that is used to track the relative path of a user file (like session stats),
    /// and the root path between the installer and WoT directory.
    /// </summary>
    public struct UserDataFile
    {
        /// <summary>
        /// Create an instance of the UserDataFile struct.
        /// </summary>
        /// <param name="dataFileToCopy">The UserDataFile struct to copy.</param>
        public UserDataFile(UserDataFile dataFileToCopy)
        {
            this.WoTRoot = dataFileToCopy.WoTRoot;
            this.TempSaveRoot = dataFileToCopy.TempSaveRoot;
            this.FilePath = dataFileToCopy.FilePath;
        }

        /// <summary>
        /// The WoT root directory where the UserDataFile is from.
        /// </summary>
        public string WoTRoot;

        /// <summary>
        /// The directory path to the installer's temporary folder for holding user files during an installation.
        /// </summary>
        public string TempSaveRoot;

        /// <summary>
        /// The relative path of the user file.
        /// </summary>
        public string FilePath;
    }

    /// <summary>
    /// An object that represents cache files generated by mods that should be backed up and restored as to not loose cache data (like session stats or auto equip data).
    /// </summary>
    public class UserFile : XmlComponent, IXmlSerializable
    {
        /// <summary>
        /// Create an instance of the UserFile class.
        /// </summary>
        public UserFile() : base()
        {

        }

        /// <summary>
        /// Create an instance of the UserFile class, copying values from a given UserFile object.
        /// </summary>
        /// <param name="userfileToCopy">The UserFile instance to copy from.</param>
        public UserFile(UserFile userfileToCopy) : base(userfileToCopy)
        {
            this.Pattern = userfileToCopy.Pattern;
        }

        /// <summary>
        /// Create an instance of the UserFile class, copying values and list contents from a given UserFile object.
        /// </summary>
        /// <param name="userfileToCopy">The UserFile instance to copy from.</param>
        /// <param name="deep">If true, copy the list of files saved.</param>
        public UserFile(UserFile userfileToCopy, bool deep) : this(userfileToCopy)
        {
            if (deep)
                foreach (UserDataFile dataFile in userfileToCopy.FilesSaved)
                    this.FilesSaved.Add(new UserDataFile(dataFile));
        }

        #region Xml serialization V1
        /// <summary>
        /// Defines a list of properties in the class to be serialized into xml attributes.
        /// </summary>
        /// <returns>A list of string property names.</returns>
        /// <remarks>Xml attributes will always be written, xml elements are optional.</remarks>
        public string[] PropertiesForSerializationAttributes()
        {
            return new string[] { nameof(Pattern) };
        }

        /// <summary>
        /// Defines a list of properties in the class to be serialized into xml elements.
        /// </summary>
        /// <returns>A list of string property names.</returns>
        /// <remarks>Xml attributes will always be written, xml elements are optional.</remarks>
        public string[] PropertiesForSerializationElements()
        {
            return new string[] { };
        }
        #endregion

        #region Xml serialization V2
        /// <summary>
        /// Creates the list of xml components (attributes and elements) to use for xml serialization according to the 1.0 xml schema.
        /// </summary>
        /// <returns>The list of xml components, describing the class property name, xml node name, and xml node type</returns>
        /// <remarks>The order of the properties in the list is used to consider where in the xml document they should be located (it tracks order).</remarks>
        /// <seealso cref="XmlDatabaseProperty"/>
        protected override List<XmlDatabaseProperty> GetXmlDatabasePropertiesV1Dot0()
        {
            List<XmlDatabaseProperty> xmlDatabaseProperties = new List<XmlDatabaseProperty>()
            {
                //list attributes
                new XmlDatabaseProperty() { XmlName = nameof(Pattern), XmlEntryType = Utilities.Enums.XmlEntryType.XmlAttribute, PropertyName = nameof(Pattern) }
            };
            return xmlDatabaseProperties;
        }

        /// <summary>
        /// Creates the list of xml components (attributes and elements) to use for xml serialization according to the 1.1 xml schema.
        /// </summary>
        /// <returns>The list of xml components, describing the class property name, xml node name, and xml node type</returns>
        /// <remarks>The order of the properties in the list is used to consider where in the xml document they should be located (it tracks order).</remarks>
        /// <seealso cref="XmlDatabaseProperty"/>
        protected override List<XmlDatabaseProperty> GetXmlDatabasePropertiesV1Dot1()
        {
            return this.GetXmlDatabasePropertiesV1Dot0();
        }

        /// <summary>
        /// Creates the list of xml components (attributes and elements) to use for xml serialization according to the 1.2 xml schema.
        /// </summary>
        /// <returns>The list of xml components, describing the class property name, xml node name, and xml node type</returns>
        /// <remarks>The order of the properties in the list is used to consider where in the xml document they should be located (it tracks order).</remarks>
        /// <seealso cref="XmlDatabaseProperty"/>
        protected override List<XmlDatabaseProperty> GetXmlDatabasePropertiesV1Dot2()
        {
            return this.GetXmlDatabasePropertiesV1Dot1();
        }
        #endregion

        /// <summary>
        /// The path or pattern to a file or files to backup to a temporary directory.
        /// </summary>
        public string Pattern { get; set; } = string.Empty;

        /// <summary>
        /// The list of actual files saved to the temporary backup directory. Contains the full path and file name
        /// </summary>
        public List<UserDataFile> FilesSaved { get; } = new List<UserDataFile>();

        /// <summary>
        /// The string representation of the UserFile object.
        /// </summary>
        /// <returns>The string pattern.</returns>
        public override string ToString()
        {
            return Pattern;
        }

        /// <summary>
        /// Create a copy of the UserFile object.
        /// </summary>
        /// <param name="userFileToCopy">The object to copy.</param>
        /// <returns>A new UserFile object with the same values.</returns>
        public static UserFile Copy(UserFile userFileToCopy)
        {
            return new UserFile(userFileToCopy);
        }

        /// <summary>
        /// Create a deep copy of the UserFile object.
        /// </summary>
        /// <param name="userFileToCopy">The object to copy.</param>
        /// <returns>A new UserFile object with the same values and new list elements with the same values.</returns>
        public static UserFile DeepCopy(UserFile userFileToCopy)
        {       
            return new UserFile(userFileToCopy, true);
        }
    }
}
