using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace FishNet.Configuring
{

    public enum StrippingTypes : int
    {
        Redirect = 0,
        Empty_Experimental = 1,
    }
    public enum SearchScopeType : int
    {
        EntireProject = 0,
        SpecificFolders = 1,
    }

    public class PrefabGeneratorConfigurations
    {
        public bool Enabled = true;
        public bool LogToConsole = true;
        public bool FullRebuild = false;
        public bool SaveChanges = true;
        public string DefaultPrefabObjectsPath = Path.Combine("Assets", "DefaultPrefabObjects.asset");
        public int SearchScope = (int)SearchScopeType.EntireProject;
        public List<string> ExcludedFolders = new List<string>();
        public List<string> IncludedFolders = new List<string>();
    }

    public class CodeStrippingConfigurations
    {
        public bool IsBuilding = false;
        public bool IsDevelopment = false;
        public bool IsHeadless = false;
        public bool StripReleaseBuilds = false;
        public int StrippingType = (int)StrippingTypes.Redirect;
    }


    public class ConfigurationData
    {
        //Non serialized doesn't really do anything, its just for me.
        [System.NonSerialized]
        public bool Loaded;

        public PrefabGeneratorConfigurations PrefabGenerator = new PrefabGeneratorConfigurations();
        public CodeStrippingConfigurations CodeStripping = new CodeStrippingConfigurations();
    }

    public static class ConfigurationDataExtension
    {
        /// <summary>
        /// Returns if a differs from b.
        /// </summary>
        public static bool HasChanged(this ConfigurationData a, ConfigurationData b)
        {
            return (a.CodeStripping.StripReleaseBuilds != b.CodeStripping.StripReleaseBuilds);
        }
        /// <summary>
        /// Copies all values from source to target.
        /// </summary>
        public static void CopyTo(this ConfigurationData source, ConfigurationData target)
        {
            target.CodeStripping.StripReleaseBuilds = source.CodeStripping.StripReleaseBuilds;
        }


        /// <summary>
        /// Writes a configuration data.
        /// </summary>
        public static void Write(this ConfigurationData cd, bool refreshAssetDatabase)
        {
            /* Why is this a thing you ask? Because Unity makes it VERY difficult to read values from
             * memory during builds since on some Unity versions the building application is on a different
             * processor. In result instead of using memory to read configurationdata the values
             * must be written to disk then load the disk values as needed.
             * 
             * Fortunatelly the file is extremely small and this does not occur often at all. The disk read
             * will occur once per script save, and once per assembly when building. */
            try
            {
                string path = Configuration.GetAssetsPath(Configuration.CONFIG_FILE_NAME);
                XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData));
                TextWriter writer = new StreamWriter(path);
                serializer.Serialize(writer, cd);
                writer.Close();
#if UNITY_EDITOR
                if (refreshAssetDatabase)
                {
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                }
#endif
            }
            catch (Exception ex)
            {
                throw new Exception($"An error occurred while writing ConfigurationData. Message: {ex.Message}");
            }

        }


        /// <summary>
        /// Writes a configuration data.
        /// </summary>
        public static void Write(this ConfigurationData cd, string path, bool refreshAssetDatabase)
        {
            /* Why is this a thing you ask? Because Unity makes it VERY difficult to read values from
             * memory during builds since on some Unity versions the building application is on a different
             * processor. In result instead of using memory to read configurationdata the values
             * must be written to disk then load the disk values as needed.
             * 
             * Fortunatelly the file is extremely small and this does not occur often at all. The disk read
             * will occur once per script save, and once per assembly when building. */
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData));
                TextWriter writer = new StreamWriter(path);
                serializer.Serialize(writer, cd);
                writer.Close();
#if UNITY_EDITOR
                if (refreshAssetDatabase)
                {
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                }
#endif
            }
            catch (Exception ex)
            {
                throw new Exception($"An error occurred while writing ConfigurationData. Message: {ex.Message}");
            }

        }

    }


}