using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using CommonLib.IO;
using CommonLib.Misc;
using CommonLib.Windows.Forms;

namespace All_Purpose_Auto_Setup
{
   class GutsConfigFileManager
   {
      // An event that can be raised, allowing other classes to
      // subscribe to it and do what they like with the message.
      public event Action<string, string, List<CommonLib.Windows.Forms.TextFormat.TextFontAndColor>> UpdateStatusDisplayAndLogEvent;

      // dictionary that stores key value pair for each entry in the GUTS config file
      public List<ConfigFileManager.Ini_KeyValue<string>> gutsConfigEntries = new List<ConfigFileManager.Ini_KeyValue<string>>();

      public ConfigFileManager.Ini_KeyValue<string> sm3seekerConfigFile = new ConfigFileManager.Ini_KeyValue<string>("");
      public ConfigFileManager.Ini_KeyValue<string> gutsBinariesLocation = new ConfigFileManager.Ini_KeyValue<string>("");

      Form m_parentForm;

      public GutsConfigFileManager(Form parentForm)
      {
         m_parentForm = parentForm;
      }

      public bool processGutsConfigFile(string sectionName)
      {
         bool setupSuccessful = true;
         string msg, errMsg = String.Empty, sourceFile, destFile = "";
         string indentation = String.Empty;
         bool performFileCopying = true;

         CommonLib.Windows.Forms.TextFormat.TextFontAndColor defaultTextProp = new CommonLib.Windows.Forms.TextFormat.TextFontAndColor("");
         CommonLib.Windows.Forms.TextFormat.TextFontAndColor textProp = new CommonLib.Windows.Forms.TextFormat.TextFontAndColor("");
         List<CommonLib.Windows.Forms.TextFormat.TextFontAndColor> textPropList = new List<CommonLib.Windows.Forms.TextFormat.TextFontAndColor>();

         // set font to default text and color
         textProp.textFont = defaultTextProp.textFont;
         textProp.textColor = Common.getSetupStepTitleColor();
         textProp.wordIndex = 0;
         textProp.wordCount = 100;
         textPropList.Add(textProp);

         DateTime dat1 = DateTime.Now;
         msg = "\n\n<-------------------Date and Time: " + dat1.ToString(@"MM/dd/yyyy     hh:mm:ss tt", System.Globalization.CultureInfo.InvariantCulture) + "------------------->";
         UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

         // set font to default text and color
         textProp.textFont = defaultTextProp.textFont;
         textProp.textColor = Common.getSetupStepTitleColor();
         textProp.wordIndex = 0;
         textProp.wordCount = 100;
         // set font size
         textProp.textFont = new Font(textProp.textFont.Name, 12);
         // set font style
         textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
         textPropList.Add(textProp);

         msg = "\n-=Processing GUTS Config File=-";
         UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

         gutsConfigEntries.Clear();

         ConfigFileManager.parseConfigInfo(sectionName, gutsConfigEntries);

         readGutsInfo();

         setupSuccessful = verifyConfigInfo();

         if (setupSuccessful)
         {

            destFile = PathManip.RemoveTrailingSlashInPath(gutsBinariesLocation.iniValue) + "\\Sm3Seeker.cfg";

            textProp.textFont = defaultTextProp.textFont;
            textProp.textColor = Color.FromArgb(233, 31, 195);
            textProp.wordIndex = 1;
            textProp.wordCount = 100;
            // set font style
            textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
            textPropList.Add(textProp);

            indentation = Common.getIndentation(1);
            msg = "\n" + indentation + "Copying " + Path.GetFileName(sm3seekerConfigFile.iniValue);
            UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

            performFileCopying = true;

            sourceFile = sm3seekerConfigFile.iniValue;
            sourceFile = PathManip.GetProperFilePathCapitalization(sourceFile);

            if (!File.Exists(sourceFile))
            {
               msg = " - FAILED. File " + sourceFile + " not found";

               // set font to default text and color
               textProp.textFont = defaultTextProp.textFont;
               textProp.textColor = Common.getSetupStatusColor(Common.EXECUTION_STATUS.FAILURE);
               textProp.wordIndex = StringManip.GetPhraseWordIndexInText(msg, "FAILED.");
               textProp.wordCount = 1;
               // set font style
               textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
               textPropList.Add(textProp);

               setupSuccessful = false;

               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

            }

            if (File.Exists(destFile) && setupSuccessful)
            {
               msg = ((frmSetupStatusDisplay)m_parentForm).displayMessageBox(MessageBoxCustom.PopUpMsgType.YESNO, null, "File " + destFile + " already exists.\n\n Would you like to overwrite it?", "Info", -1);

               if (String.Equals(msg, "no", StringComparison.OrdinalIgnoreCase))
               {
                  // set font to default text and color
                  textProp.textFont = defaultTextProp.textFont;
                  textProp.textColor = Common.getSetupStatusColor(Common.EXECUTION_STATUS.USER_SKIP);
                  textProp.wordIndex = 0;
                  textProp.wordCount = 2;
                  // set font style
                  textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
                  textPropList.Add(textProp);

                  indentation = Common.getIndentation(2);
                  msg = "\n" + indentation + "- SKIPPED by user.";
                  UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);
                  performFileCopying = false;
               }
            }

            if (setupSuccessful && performFileCopying)
            {
               indentation = Common.getIndentation(2);
               msg = "\n" + indentation + "- From: " + sourceFile;
               msg += "\n" + indentation + "- To: " + destFile;

               // set font to default text and color
               textProp.textFont = defaultTextProp.textFont;
               textProp.textColor = defaultTextProp.textColor;
               textProp.wordIndex = StringManip.GetPhraseWordIndexInText(msg, "From:");
               textProp.wordCount = 1;
               // set font style
               textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
               textPropList.Add(textProp);

               // set font to default text and color
               textProp.textFont = defaultTextProp.textFont;
               textProp.textColor = defaultTextProp.textColor;
               textProp.wordIndex = StringManip.GetPhraseWordIndexInText(msg, "To:");
               textProp.wordCount = 1;
               // set font style
               textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
               textPropList.Add(textProp);

               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

               setupSuccessful = FileManip.CopyFile(Path.GetDirectoryName(sourceFile), sourceFile, Path.GetDirectoryName(destFile), destFile, true, FileAttributes.Normal, ref errMsg);

               if (setupSuccessful)
               {
                  // set font to default text and color
                  textProp.textFont = defaultTextProp.textFont;
                  textProp.textColor = Common.getSetupStatusColor(Common.EXECUTION_STATUS.SUCCESS);
                  textProp.wordIndex = 0;
                  textProp.wordCount = 2;
                  // set font style
                  textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
                  textPropList.Add(textProp);

                  indentation = Common.getIndentation(2);
                  msg = "\n" + indentation + "- SUCCESS.";
                  UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

                  // set file to read-write access
                  if (FileManip.SetFileAttributeToReadAndWrite(destFile, ref errMsg))
                  {
                     if (gutsConfigEntries.Count > 0)
                     {
                        textProp.textFont = defaultTextProp.textFont;
                        textProp.textColor = Color.FromArgb(233, 31, 195);
                        textProp.wordIndex = 2;
                        textProp.wordCount = 100;
                        // set font style
                        textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
                        textPropList.Add(textProp);

                        indentation = Common.getIndentation(1);
                        msg = "\n" + indentation + "Modifying file " + destFile;
                        UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

                        string delimiter = "[,]";

                        // first we have to determine the correct keys based on the generic key provided in the INI file
                        // and add these dynamic keys to the existing dictionary of all the correct keys
                        foreach (ConfigFileManager.Ini_KeyValue<string> configEntry in gutsConfigEntries)
                        {
                           List<string> triplet = new List<string>(configEntry.iniValue.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries));

                           if (triplet.Count > 0)
                              triplet[0] = triplet[0].Trim();

                           if (triplet.Count > 1)
                              triplet[1] = triplet[1].Trim();

                           if (triplet.Count > 2)
                              triplet[2] = triplet[2].Trim();

                           // section, key and value exist
                           if (triplet.Count == 3 && triplet[0].Length > 0 && triplet[1].Length > 0 && triplet[2].Length > 0)
                           {
                              setupSuccessful = modifyGutsConfigFile(destFile, triplet[0], triplet[1], triplet[2]);

                              if (!setupSuccessful)
                                 break;
                           }
                        }
                     }
                  }
               }
               else
               {
                  // set font to default text and color
                  textProp.textFont = defaultTextProp.textFont;
                  textProp.textColor = Common.getSetupStatusColor(Common.EXECUTION_STATUS.FAILURE);
                  textProp.wordIndex = 0;
                  textProp.wordCount = 2;
                  // set font style
                  textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
                  textPropList.Add(textProp);

                  indentation = Common.getIndentation(2);
                  msg = "\n" + indentation + "- FAILED. " + errMsg;
                  UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

                  setupSuccessful = false;
               }
            }
         }
         return setupSuccessful;
      }

      public bool modifyGutsConfigFile(string configFile, string configSectionName, string configKey, string configValue)
      {
         bool setupSuccessful = true;
         string msg, errMsg = String.Empty;

         string indentation = String.Empty;
         Dictionary<string, string> gutsSourceFileToDestFile = new Dictionary<string, string>();

         CommonLib.Windows.Forms.TextFormat.TextFontAndColor defaultTextProp = new CommonLib.Windows.Forms.TextFormat.TextFontAndColor("");
         CommonLib.Windows.Forms.TextFormat.TextFontAndColor textProp = new CommonLib.Windows.Forms.TextFormat.TextFontAndColor("");
         List<CommonLib.Windows.Forms.TextFormat.TextFontAndColor> textPropList = new List<CommonLib.Windows.Forms.TextFormat.TextFontAndColor>();

         string pattern = @"(section +" + configSectionName + @"(?:(?!\nsection).)*\n" + configKey + @" +)[^;\r\n]+";
         string replacement = "${1}" + configValue;

         setupSuccessful = FileManip.ReplaceTextInFile(configFile, pattern, replacement, ref errMsg);

         indentation = Common.getIndentation(2);
         msg = "\n" + indentation + "Setting " + configKey + "=" + configValue + " in section " + configSectionName;
         if (setupSuccessful)
         {
            msg += " - SUCCESS.";

            // set font to default text and color
            textProp.textFont = defaultTextProp.textFont;
            textProp.textColor = Common.getSetupStatusColor(Common.EXECUTION_STATUS.SUCCESS);
            textProp.wordIndex = StringManip.GetPhraseWordIndexInText(msg, "SUCCESS.");
            textProp.wordCount = 1;
            // set font style
            textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
            textPropList.Add(textProp);
         }
         else
         {
            msg += " - FAILED.";
            if (errMsg.Length > 0)
               msg += " " + errMsg;

            // set font to default text and color
            textProp.textFont = defaultTextProp.textFont;
            textProp.textColor = Common.getSetupStatusColor(Common.EXECUTION_STATUS.FAILURE);
            textProp.wordIndex = StringManip.GetPhraseWordIndexInText(msg, "FAILED.");
            textProp.wordCount = 1;
            // set font style
            textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
            textPropList.Add(textProp);

            setupSuccessful = false;
         }

         UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

         return setupSuccessful;

      }

      public void readGutsInfo()
      {
         string[] keyDataPair;
         Dictionary<string, string> keyAndValuePair = new Dictionary<string, string>();

         string sectionName;

         string[] sectionData;

         sectionName = ConfigFileManager.enum_INI_SECTION_NAMES.GUTS_Info.ToString();
         sectionData = ConfigFileManager.ms_configGeneralInfo.iniFile.ReadSectionData(sectionName);

         gutsBinariesLocation.iniKeyName = "Guts_Bin_Dir";
         gutsBinariesLocation.iniSectionName = sectionName;

         sm3seekerConfigFile.iniKeyName = "sm3seeker_config_file";
         sm3seekerConfigFile.iniSectionName = sectionName;

         foreach (string path in sectionData)
         {
            keyDataPair = path.Split('=');

            if (String.Equals(keyDataPair[0], gutsBinariesLocation.iniKeyName, StringComparison.OrdinalIgnoreCase))
            {
               if (keyDataPair.Length == 2)
               {
                  gutsBinariesLocation.iniValue = keyDataPair[1];
               }
            }
            else if (String.Equals(keyDataPair[0], sm3seekerConfigFile.iniKeyName, StringComparison.OrdinalIgnoreCase))
            {
               if (keyDataPair.Length == 2 && keyDataPair[1].Length > 0)
               {
                  sm3seekerConfigFile.iniValue = Path.GetFullPath(keyDataPair[1]);
               }
            }
         }
      }

      bool verifyConfigInfo()
      {
         bool setupSuccessful = true;
         string indentation = String.Empty;
         string msg, tempPath;

         List<CommonLib.Windows.Forms.TextFormat.TextFontAndColor> textPropList = new List<CommonLib.Windows.Forms.TextFormat.TextFontAndColor>();

         if (gutsBinariesLocation.iniValue.Length == 0)
         {
            indentation = Common.getIndentation(2);
            msg = "\n" + indentation + "- FAILED. "
                     + "\n" + indentation + "File: " + ConfigFileManager.ms_configGeneralInfo.pathAndNameOfConfigFile
                     + "\n" + indentation + "Section: " + gutsBinariesLocation.iniSectionName
                     + "\n" + indentation + "Key: " + gutsBinariesLocation.iniKeyName
                     + "\n" + indentation + "Value: " + gutsBinariesLocation.iniValue
                     + "\n" + indentation + "Error Description: Either one or a combination of Section, Key, or Value is not defined in the INI file.";

            Common.formatConfigIniFailureMessage(msg, textPropList);

            UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

            setupSuccessful = false;
         }
         else if (sm3seekerConfigFile.iniValue.Length == 0)
         {
            indentation = Common.getIndentation(2);
            msg = "\n" + indentation + "- FAILED. "
                     + "\n" + indentation + "File: " + ConfigFileManager.ms_configGeneralInfo.pathAndNameOfConfigFile
                     + "\n" + indentation + "Section: " + sm3seekerConfigFile.iniSectionName
                     + "\n" + indentation + "Key: " + sm3seekerConfigFile.iniKeyName
                     + "\n" + indentation + "Value: " + sm3seekerConfigFile.iniValue
                     + "\n" + indentation + "Error Description: Either one or a combination of Section, Key, or Value is not defined in the INI file.";

            Common.formatConfigIniFailureMessage(msg, textPropList);

            UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

            setupSuccessful = false;
         }

         if (setupSuccessful)
         {
            tempPath = Path.GetFullPath(gutsBinariesLocation.iniValue);

            if (!Directory.Exists(gutsBinariesLocation.iniValue))
            {
               indentation = Common.getIndentation(2);
               msg = "\n" + indentation + "- FAILED. "
                        + "\n" + indentation + "File: " + ConfigFileManager.ms_configGeneralInfo.pathAndNameOfConfigFile
                        + "\n" + indentation + "Section: " + gutsBinariesLocation.iniSectionName
                        + "\n" + indentation + "Key: " + gutsBinariesLocation.iniKeyName
                        + "\n" + indentation + "Value: " + gutsBinariesLocation.iniValue
                        + "\n" + indentation + "Error Description: The path defined in the value above is invalid. Translated path " + tempPath;

               Common.formatConfigIniFailureMessage(msg, textPropList);

               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

               setupSuccessful = false;
            }
            else
               gutsBinariesLocation.iniValue = tempPath;
         }

         if (setupSuccessful)
         {
            tempPath = Path.GetFullPath(sm3seekerConfigFile.iniValue); ;

            if (!File.Exists(sm3seekerConfigFile.iniValue))
            {
               indentation = Common.getIndentation(2);
               msg = "\n" + indentation + "- FAILED. "
                        + "\n" + indentation + "File: " + ConfigFileManager.ms_configGeneralInfo.pathAndNameOfConfigFile
                        + "\n" + indentation + "Section: " + sm3seekerConfigFile.iniSectionName
                        + "\n" + indentation + "Key: " + sm3seekerConfigFile.iniKeyName
                        + "\n" + indentation + "Value: " + sm3seekerConfigFile.iniValue
                        + "\n" + indentation + "Error Description: The path defined in the value above is invalid. Translated path " + tempPath;

               Common.formatConfigIniFailureMessage(msg, textPropList);

               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

               setupSuccessful = false;
            }
            else
               sm3seekerConfigFile.iniValue = tempPath;
         }

         return setupSuccessful;
      }
   }
}
