using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Globalization;

namespace s3sr
{
    class Settings
    {
        #region Registry Settings

        public static bool usingSteam = false;
        public static bool firstRun = true;
        public static bool alertInfo = true;
        public static bool useStoreAlternativePath = false;
        public static bool searchSubFiles_Custom = true;
        public static bool searchSubFiles_Store = true;
        public static bool decryptStore = false;
        
        public static bool hasBASE = false;
        public static string path_gameBASE = "";
        public static string path_BASE = "";

        public static bool hasEP01 = false;
        public static string path_gameEP01 = "";
        public static string path_EP01 = "";

        public static bool hasSP01 = false;
        public static string path_gameSP01 = "";
        public static string path_SP01 = "";

        public static bool hasEP02 = false;
        public static string path_gameEP02 = "";
        public static string path_EP02 = "";

        public static bool hasSP02 = false;
        public static string path_gameSP02 = "";
        public static string path_SP02 = "";

        public static bool hasEP03 = false;        
        public static string path_gameEP03 = "";
        public static string path_EP03 = "";

        public static bool hasSP03 = false;
        public static string path_gameSP03 = "";
        public static string path_SP03 = "";

        public static string path_Store = "";
        public static string path_StoreAlternative = "";
        public static string path_Custom = "";
        public static string path_Output = "";

        public static CheckUpdateState checkUpdate = CheckUpdateState.GUI;
        public enum CheckUpdateState : int
        {
            Off = 0,
            Always = 1,
            GUI = 2
        }
        #endregion

        #region Functions

        /// <summary>
        /// Convert Boolean to Integer representation (1 or 0)
        /// </summary>
        /// <param name="bol">Boolean Value</param>
        /// <returns>Integer representation of the boolean <paramref name="bol"/></returns>
        private static int BoolToInt(bool bol)
        {
            return (bol ? 1 : 0);
        }

        /// <summary>
        /// Read current registry settings
        /// </summary>
        /// <param name="forceFirstRun">(Optional) Attempt to generate game paths from values stored by The Sims 3</param>
        /// <returns>bool, true if readed successfully, false if did not</returns>
        public static bool Read(bool forceFirstRun = false)
        {
            RegistryKey key;
            string Sims_root = @"Software\Sims";
            
            #region Check Steam Version
            bool gotSteam = false;

            try
            {
                key = Registry.CurrentUser.OpenSubKey(@"Software\awtmk\ts3tools\s3sr", false);
                if (key != null)
                {
                    if (key.GetValue("Steam") != null)
                        if (Convert.ToUInt32(key.GetValue("Steam").ToString(), 16) == 1)
                        {
                            usingSteam = true;
                            gotSteam = true;
                            Sims_root = @"Software\Sims(Steam)";
                        }
                    key.Close();
                }
            }
            catch { }

            if (!gotSteam)
            {
                key = Registry.LocalMachine.OpenSubKey(@"Software\Sims(Steam)", false);
                if (key != null)
                {
                    switch (MessageBox.Show("It seems you have The Sims 3, Steam version.\nDo you confirm?", "Steam Version", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                    {
                        case DialogResult.Yes:
                            usingSteam = true;
                            Sims_root = @"Software\Sims(Steam)";
                            break;
                        case DialogResult.No:
                            usingSteam = false; // Doesn't make any sense...
                            break;
                    }
                    key.Close();
                }
            }
            #endregion

            #region Read Game Default Paths
            try
            {
                #region Read BASE Settings
                key = Registry.LocalMachine.OpenSubKey(Sims_root + @"\The Sims 3", false);
                if (key == null)
                {
                    hasBASE = false;
                    MessageBox.Show("Could not read Base Game settings from registry.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    hasBASE = true;
                    path_gameBASE = key.GetValue("Install Dir").ToString();
                }
                key.Close();
                #endregion

                #region Read EP01 Settings
                key = Registry.LocalMachine.OpenSubKey(Sims_root + @"\The Sims 3 World Adventures", false);
                if (key == null)
                    hasEP01 = false;
                else
                {
                    hasEP01 = true;
                    path_gameEP01 = key.GetValue("Install Dir").ToString();
                }
                key.Close();
                #endregion

                #region Read SP01 Settings
                key = Registry.LocalMachine.OpenSubKey(Sims_root + (usingSteam ? @"\The Sims 3 High End Loft Stuff" : @"\The Sims 3 High-End Loft Stuff"), false);
                if (key == null)
                    hasSP01 = false;
                else
                {
                    hasSP01 = true;
                    path_gameSP01 = key.GetValue("Install Dir").ToString();
                }
                key.Close();
                #endregion

                #region Read EP02 Settings
                key = Registry.LocalMachine.OpenSubKey(Sims_root + @"\The Sims 3 Ambitions", false);
                if (key == null)
                    hasEP02 = false;
                else
                {
                    hasEP02 = true;
                    path_gameEP02 = key.GetValue("Install Dir").ToString();
                }
                key.Close();
                #endregion

                #region Read SP02 Settings
                key = Registry.LocalMachine.OpenSubKey(Sims_root + @"\The Sims 3 Fast Lane Stuff", false);
                if (key == null)
                    hasSP02 = false;
                else
                {
                    hasSP02 = true;
                    path_gameSP02 = key.GetValue("Install Dir").ToString();
                }
                key.Close();
                #endregion

                #region Read EP03 Settings
                key = Registry.LocalMachine.OpenSubKey(Sims_root + @"\The Sims 3 Late Night", false);
                if (key == null)
                    hasEP03 = false;
                else
                {
                    hasEP03 = true;
                    path_gameEP03 = key.GetValue("Install Dir").ToString();
                }
                key.Close();
                #endregion

                #region Read SP03 Settings
                key = Registry.LocalMachine.OpenSubKey(Sims_root + @"\The Sims 3 Outdoor Living Stuff", false);
                if (key == null)
                    hasSP03 = false;
                else
                {
                    hasSP03 = true;
                    path_gameSP03 = key.GetValue("Install Dir").ToString();
                }
                key.Close();
                #endregion
            }
            catch (Exception exceptionLoad)
            {
                MessageBox.Show(exceptionLoad.ToString(), "Exception while Reading Default Settings", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ErrorReport.CreateExceptionReport(exceptionLoad, "Exception @ \"U2V0dGluZ3MuY3M= 123\";");
            }
            #endregion

            #region Read/Create Application Settings
            try 
            {
                key = Registry.CurrentUser.OpenSubKey(@"Software\awtmk\ts3tools\s3sr", true);
                if (key == null)
                {
                    key = Registry.CurrentUser.CreateSubKey(@"Software\awtmk");
                    key.SetValue("Blog", "http://awtmk.blogspot.com/");
                    key.SetValue("SourceForge", "http://sourceforge.net/users/awtmk");
                    key = key.CreateSubKey("ts3tools");
                    key.SetValue("", "http://sourceforge.net/projects/ts3tools/");
                    key = key.CreateSubKey("s3sr");
                    key.SetValue("", Application.ProductVersion);
                }

                #region Read General Settings
                if (key.GetValue("Steam") != null)
                    usingSteam = Convert.ToUInt32(key.GetValue("Steam").ToString(), 16) == 1;
                else
                    key.SetValue("Steam", usingSteam, RegistryValueKind.DWord);

                if (key.GetValue("FirstRun") != null)
                    firstRun = Convert.ToUInt32(key.GetValue("FirstRun").ToString(), 16) == 1;
                else
                {
                    key.SetValue("FirstRun", 1, RegistryValueKind.DWord);
                    firstRun = true;
                }
                
                if (key.GetValue("AlertInfo") != null)
                    alertInfo = Convert.ToUInt32(key.GetValue("AlertInfo").ToString(), 16) == 1;
                else
                {
                    key.SetValue("AlertInfo", 0, RegistryValueKind.DWord);
                    alertInfo = false;
                }

                if (key.GetValue("PathOutput") != null)
                    path_Output = key.GetValue("PathOutput").ToString().Trim();
                else
                {
                    key.SetValue("PathOutput", "");
                    path_Output = "";
                }

                if (key.GetValue("CheckUpdates") != null)
                    checkUpdate = (CheckUpdateState) Convert.ToUInt32(key.GetValue("CheckUpdates").ToString(), 16);
                else
                {
                    key.SetValue("CheckUpdates", CheckUpdateState.GUI, RegistryValueKind.DWord);
                    checkUpdate = CheckUpdateState.GUI;
                }
                #endregion

                #region Read Game Paths Settings

                #region Read BASE Path
                if (key.GetValue("PathBASE") != null)
                    path_BASE = key.GetValue("PathBASE").ToString().Trim();
                else
                {
                    key.SetValue("PathBASE", path_gameBASE);
                    path_BASE = path_gameBASE;
                }
                #endregion

                #region Read EP01 Path
                if (key.GetValue("PathEP01") != null)
                    path_EP01 = key.GetValue("PathEP01").ToString().Trim();
                else
                {
                    key.SetValue("PathEP01", path_gameEP01);
                    path_EP01 = path_gameEP01;
                }
                #endregion

                #region Read SP01 Path
                if (key.GetValue("PathSP01") != null)
                    path_SP01 = key.GetValue("PathSP01").ToString().Trim();
                else
                {
                    key.SetValue("PathSP01", path_gameSP01);
                    path_SP01 = path_gameSP01;
                }
                #endregion

                #region Read EP02 Path
                if (key.GetValue("PathEP02") != null)
                    path_EP02 = key.GetValue("PathEP02").ToString().Trim();
                else
                {
                    key.SetValue("PathEP02", path_gameEP02);
                    path_EP02 = path_gameEP02;
                }
                #endregion

                #region Read SP02 Path
                if (key.GetValue("PathSP02") != null)
                    path_SP02 = key.GetValue("PathSP02").ToString().Trim();
                else
                {
                    key.SetValue("PathSP02", path_gameSP02);
                    path_SP02 = path_gameSP02;
                }
                #endregion

                #region Read EP03 Path
                if (key.GetValue("PathEP03") != null)
                    path_EP03 = key.GetValue("PathEP03").ToString().Trim();
                else
                {
                    key.SetValue("PathEP03", path_gameEP03);
                    path_EP03 = path_gameEP03;
                }
                #endregion

                #region Read SP03 Path
                if (key.GetValue("PathSP03") != null)
                    path_SP03 = key.GetValue("PathSP03").ToString().Trim();
                else
                {
                    key.SetValue("PathSP03", path_gameSP03);
                    path_SP03 = path_gameSP03;
                }
                #endregion
                
                #region Read Store Paths
                if (key.GetValue("PathStore") != null)
                    path_Store = key.GetValue("PathStore").ToString().Trim();
                else
                {
                    path_Store = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Electronic Arts\";
                    #region Switch OS Language
                    switch (System.Globalization.CultureInfo.CurrentUICulture.Name)
                    {
                        case "fr-FR": // French
                            path_Store += @"Les Sims 3\DCCache";
                            break;
                        default:
                            path_Store += @"The Sims 3\DCCache";
                            break;
                    }
                    #endregion
                    key.SetValue("PathStore", path_Store);
                }

                if (key.GetValue("PathStoreAlternative") != null)
                    path_StoreAlternative = key.GetValue("PathStoreAlternative").ToString().Trim();
                else
                {
                    key.SetValue("PathStoreAlternative", "");
                    path_StoreAlternative = "";
                }

                if (key.GetValue("SearchSubFilesStore") != null)
                    searchSubFiles_Store = Convert.ToUInt32(key.GetValue("SearchSubFilesStore").ToString(), 16) == 1;
                else
                {
                    key.SetValue("SearchSubFilesStore", 0, RegistryValueKind.DWord);
                    searchSubFiles_Store = false;
                }

                if (key.GetValue("UseStoreAlternativePath") != null)
                    useStoreAlternativePath = Convert.ToUInt32(key.GetValue("UseStoreAlternativePath").ToString(), 16) == 1;
                else
                {
                    key.SetValue("UseStoreAlternativePath", 0, RegistryValueKind.DWord);
                    useStoreAlternativePath = false;
                }

                if (key.GetValue("DecryptStoreFiles") != null)
                    decryptStore = Convert.ToUInt32(key.GetValue("DecryptStoreFiles").ToString(), 16) == 1;
                else
                {
                    key.SetValue("DecryptStoreFiles", 0, RegistryValueKind.DWord);
                    decryptStore = false;
                }

                #endregion

                #region Read Custom Paths
                if (key.GetValue("PathCustom") != null)
                    path_Custom = key.GetValue("PathCustom").ToString().Trim();
                else
                {
                    path_Custom = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Electronic Arts\The Sims 3\Mods";
                    key.SetValue("PathCustom", path_Custom);
                }

                if (key.GetValue("SearchSubFilesCustom") != null)
                    searchSubFiles_Custom = Convert.ToUInt32(key.GetValue("SearchSubFilesCustom").ToString(), 16) == 1;
                else
                {
                    key.SetValue("SearchSubFilesCustom", 1, RegistryValueKind.DWord);
                    searchSubFiles_Custom = true;
                }
                #endregion

                #endregion

                key.Close();

                #region Auto-Generate Game Paths (forceFirstRun || firstRun)
                if (forceFirstRun || firstRun)
                {
                    path_BASE = path_gameBASE;
                    path_EP01 = path_gameEP01;
                    path_SP01 = path_gameSP01;
                    path_EP02 = path_gameEP02;
                    path_SP02 = path_gameSP02;
                    path_EP03 = path_gameEP03;
                    path_SP03 = path_gameSP03;
                }
                #endregion

                #region Create Script Extension if firstRun
                if (forceFirstRun || firstRun)
                    Settings.CreateExtensionRef();
                #endregion

            }
            catch (Exception exceptionLoad)
            {
                MessageBox.Show(exceptionLoad.ToString(), "Exception while Read/Create Application Settings", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ErrorReport.CreateExceptionReport(exceptionLoad, "Exception @ \"U2V0dGluZ3MuY3M= 166\";");
                Environment.Exit(0);
            }
            #endregion

            return true;
        }

        /// <summary>
        /// Save current settings to application registry
        /// </summary>
        public static void Save()
        {
            RegistryKey key = null;
            try
            {
                #region Save Registry Settings
                key = Registry.CurrentUser.OpenSubKey(@"Software\awtmk\ts3tools\s3sr", true);
                key.SetValue("", Application.ProductVersion);
                key.SetValue("Steam", BoolToInt(usingSteam), RegistryValueKind.DWord);
                key.SetValue("AlertInfo", BoolToInt(alertInfo), RegistryValueKind.DWord);
                key.SetValue("FirstRun", (BoolToInt(firstRun) == 1 ? 0 : 0), RegistryValueKind.DWord);
                key.SetValue("CheckUpdates", checkUpdate, RegistryValueKind.DWord);
                key.SetValue("UseStoreAlternativePath", BoolToInt(useStoreAlternativePath), RegistryValueKind.DWord);
                key.SetValue("PathBASE", path_BASE);
                key.SetValue("PathEP01", path_EP01);
                key.SetValue("PathSP01", path_SP01);
                key.SetValue("PathEP02", path_EP02);
                key.SetValue("PathSP02", path_SP02);
                key.SetValue("PathEP03", path_EP03);
                key.SetValue("PathSP03", path_SP03);
                key.SetValue("PathStore", path_Store);
                key.SetValue("PathStoreAlternative", path_StoreAlternative);
                key.SetValue("SearchSubFilesStore", BoolToInt(searchSubFiles_Store), RegistryValueKind.DWord);
                key.SetValue("DecryptStoreFiles", BoolToInt(decryptStore), RegistryValueKind.DWord);
                key.SetValue("PathCustom", path_Custom);
                key.SetValue("SearchSubFilesCustom", BoolToInt(searchSubFiles_Custom), RegistryValueKind.DWord);
                key.SetValue("PathOutput", path_Output);
                key.Close();
                #endregion
            }
            catch (Exception exceptionSave)
            {
                MessageBox.Show(exceptionSave.ToString(), "Exception while Saving Settings", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ErrorReport.CreateExceptionReport(exceptionSave, "Exception @ \"U2V0dGluZ3MuY3M= 339\";");
                Environment.Exit(0);
            }
            finally
            {
                key.Close();
                key = null;
            }
        }

        public static void CreateExtensionRef()
        {
            try
            {
                Extension s3sr = new Extension("aWT.ts3tools.s3sr", "s3sr", "s3sr Script", Application.ExecutablePath + ",0");
                if (s3sr.CreateExtension())
                {
                    ExtensionCommand cmd = new ExtensionCommand("Run", "Run Script in s3sr",
                        new ExtensionShellCommand(Application.ExecutablePath, new string[] { "%1" }),
                        Application.ExecutablePath + ",0");
                    s3sr.AddCommand(cmd);
                    s3sr.CreateCommands();
                }
                s3sr = null;
            }
            catch (Exception exceptionExt)
            {
                MessageBox.Show(exceptionExt.ToString(), "Exception while Saving", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ErrorReport.CreateExceptionReport(exceptionExt, "Exception @ \"U2V0dGluZ3MuY3M= 371\";");
                return;
            }
        }

        public static void DeleteExtensionRef()
        {
            try
            {
                Registry.ClassesRoot.DeleteSubKey(".s3sr", false);
                Registry.ClassesRoot.DeleteSubKeyTree("aWT.ts3tools.s3sr");
            }
            catch
            {
                return;
            }
        }
        #endregion
    }
}