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

namespace All_Purpose_Auto_Setup
{
   class SetupMiscellaneous
   {
      // 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;

      public Dictionary<string, string> environmentVars = new Dictionary<string, string>();

      public Dictionary<string, string> userPrompt = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

      Form m_parentForm;

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

      public bool setEnvironmentVariables(string sectionName)
      {
         bool setupSuccessful = true;
         string msg;
         string indentation = String.Empty;

         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-=Setting System Environment Variables=-";
         UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

         environmentVars.Clear();

         ConfigFileManager.parseConfigInfo(sectionName, environmentVars);

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

               indentation = Common.getIndentation(1);
               msg = "\n" + indentation + "- SKIPPED. Nothing to set";
               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);
            }

            foreach (KeyValuePair<string, string> entry in environmentVars)
            {
               if (String.Equals(entry.Key, "path", StringComparison.OrdinalIgnoreCase))
               {
                  setupSuccessful = processPathEnvironmentVariable(entry.Value);
               }
               else
               {
                  indentation = Common.getIndentation(1);
                  msg = "\n" + indentation + entry.Key + "=" + entry.Value;
                  try
                  {
                     System.Environment.SetEnvironmentVariable(entry.Key, entry.Value, EnvironmentVariableTarget.Machine);

                     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);
                  }
                  catch (Exception e)
                  {
                     msg += " - FAILED. (" + e.Message;

                     uint code = (uint)e.HResult;

                     if (code == 0x8013150a)
                     {
                        msg += " Need ADMIN privilege.";
                     }

                     msg += ")";

                     // 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 (!setupSuccessful)
                  break;
            }
         }
         return setupSuccessful;
      }

      public bool processPathEnvironmentVariable(string value)
      {
         bool setupSuccessful = true;

         string msg;
         string indentation = String.Empty, currentPathEnvVar = "";

         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>();

         List<string> newPathList = new List<string>(value.Split(','));

         try
         {
            currentPathEnvVar = System.Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
         }
         catch (Exception e)
         {
            indentation = Common.getIndentation(1);
            msg = "\n" + indentation + "Querying system environment variable \"Path\" - FAILED. (" + e.Message + ")";

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

            UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

            setupSuccessful = false;
         }

         if (setupSuccessful)
         {
            List<string> currentPathList = new List<string>(currentPathEnvVar.Split(';'));

            indentation = Common.getIndentation(1);
            foreach (string item in newPathList)
            {
               string path = item.Trim();

               if (currentPathList.Count == 0)
               {
                  currentPathEnvVar = path;

                  msg = "\n" + indentation + " Path=" + path;

                  try
                  {
                     System.Environment.SetEnvironmentVariable("Path", currentPathEnvVar, EnvironmentVariableTarget.Machine);

                     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);
                  }
                  catch (Exception e)
                  {
                     msg += " - FAILED. (" + e.Message + ")";

                     // 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;
                  }
               }
               else if (currentPathList.FindIndex(x => x == path) < 0 && currentPathList.FindIndex(x => x == PathManip.RemoveTrailingSlashInPath(path)) < 0)
               {
                  currentPathEnvVar += ";" + path;
                  msg = "\n" + indentation + " Path={Path};" + path;

                  try
                  {
                     System.Environment.SetEnvironmentVariable("Path", currentPathEnvVar, EnvironmentVariableTarget.Machine);

                     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);
                  }
                  catch (Exception e)
                  {
                     msg += " - FAILED. (" + e.Message;

                     uint code = (uint)e.HResult;

                     if (code == 0x8013150a)
                     {
                        msg += " Need ADMIN privilege.";
                     }

                     msg += ")";

                     // 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;
                  }
               }
               else
               {
                  msg = "\n" + indentation + "Path=" + "{Path};" + path;

                  msg += " - SKIPPED. " + path + " already exists in {Path}";

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

               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

               if (!setupSuccessful)
                  break;

            }
         }
         return setupSuccessful;
      }

      public bool promptUser(string sectionName)
      {
         bool setupSuccessful = true;
         string msg, displayMsg, result;
         string indentation = String.Empty;

         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-=User Prompt=-";
         UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

         userPrompt.Clear();

         ConfigFileManager.parseConfigInfo(sectionName, userPrompt);

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

               indentation = Common.getIndentation(1);
               msg = "\n" + indentation + "- SKIPPED. No-operation";
               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);
            }
            else
            {
               if (!userPrompt.ContainsKey("prompt_message"))
               {
                  msg = "\n" + indentation + "- FAILED. (Expecting key \"prompt_message\" in section \"" + sectionName + "\")";
                  // 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;
               }

               if (setupSuccessful)
               {
                  if (!userPrompt.ContainsKey("prompt_message_type"))
                  {
                     msg = "\n" + indentation + "- FAILED. Expecting key \"prompt_message_type\" in section \"" + sectionName + "\"";
                     // 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;
                  }
               }

               if (setupSuccessful)
               {
                  indentation = Common.getIndentation(1);
                  msg = "\n" + indentation + "Promp user";

                  displayMsg = Regex.Replace(userPrompt["prompt_message"], @"\{newline\}", "\n");

                  if (String.Equals(userPrompt["prompt_message_type"], MessageBoxCustom.PopUpMsgType.YESNO.ToString(), StringComparison.CurrentCultureIgnoreCase))
                     result = ((frmSetupStatusDisplay)m_parentForm).displayMessageBox(MessageBoxCustom.PopUpMsgType.YESNO, null, displayMsg, "Info", -1);
                  else if (String.Equals(userPrompt["prompt_message_type"], MessageBoxCustom.PopUpMsgType.OKCANCEL.ToString(), StringComparison.CurrentCultureIgnoreCase))
                     result = ((frmSetupStatusDisplay)m_parentForm).displayMessageBox(MessageBoxCustom.PopUpMsgType.OKCANCEL, null, displayMsg, "Info", -1);
                  else
                     result = ((frmSetupStatusDisplay)m_parentForm).displayMessageBox(MessageBoxCustom.PopUpMsgType.INFO, null, displayMsg, "Info", -1);

                  if (Regex.IsMatch(result, @"(yes|ok)", RegexOptions.IgnoreCase))
                  {
                     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. (User selected to abort the operation)";

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