using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.IO;
using System.Security.AccessControl;
using System.Management;
using System.Security.Principal;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Drawing;

using CommonLib.Windows.Forms;
using CommonLib.IO;
using CommonLib.Misc;

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

      Form m_parentForm;

      private bool dotNetSecurityZoneSettingSuccessful;

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

      // modify trust levels for security zones
      public bool adjustZoneSecurityForDotNetFrameWork2Pt0(string sectionName)
      {
         bool setupSuccessful = true;
         string indentation = String.Empty, platformStr;

         string dotNetFrameWork2_32bit_Path = @"C:\Windows\Microsoft.NET\Framework\v2.0.50727";
         string dotNetFrameWork2_64bit_Path = @"C:\Windows\Microsoft.NET\Framework64\v2.0.50727";
         string dotNetFrameWork2_Bin_Path;
         string caspolApp = String.Empty;

         List<string> securityZoneNames = new List<string>() { "My_Computer_Zone", "LocalIntranet_Zone", "Internet_Zone", "Trusted_Zone", "Restricted_Zone" };
         List<string> trustLevels = new List<string>() { "FullTrust", "LocalIntranet", "Internet", "Nothing" };

         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 msg;

         if (ConfigFileManager.ms_configGeneralInfo.is32BitPlatform)
         {
            platformStr = "32-bit";
            dotNetFrameWork2_Bin_Path = dotNetFrameWork2_32bit_Path;
         }
         else
         {
            platformStr = "64-bit";
            dotNetFrameWork2_Bin_Path = dotNetFrameWork2_64bit_Path;
         }

         // 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 .NET Framework 2.0 (" + platformStr + ") Security Zone Trust Level=-";
         UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

         if (setupSuccessful)
         {
            caspolApp = dotNetFrameWork2_Bin_Path + "\\caspol.exe";

            if (!Directory.Exists(dotNetFrameWork2_32bit_Path))
            {
               // 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(1);
               msg = "\n" + indentation + "- FAILED. .NET Framework 2.0 (" + platformStr + ") is not installed.";
               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);
               ((frmSetupStatusDisplay)m_parentForm).displayMessageBox(MessageBoxCustom.PopUpMsgType.ERROR, null, "Unable to detect the presence .NET Framework 2.0 (" + platformStr + ").\n\n Please install .NET Framework 2.0 before continuing...", "ERROR!!!", -1);
               setupSuccessful = false;
            }
            else if (!File.Exists(caspolApp))
            {
               // 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(1);
               msg = "\n" + indentation + "- FAILED. " + caspolApp + " not found.";
               UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);
               ((frmSetupStatusDisplay)m_parentForm).displayMessageBox(MessageBoxCustom.PopUpMsgType.ERROR, null, "Unable to detect the presence .NET Framework 2.0 (" + platformStr + ").\n\n Please install .NET Framework 2.0 before continuing...", "ERROR!!!", -1);
               setupSuccessful = false;
            }
            else
            {
               dotNetSecurityZoneSettingSuccessful = false;
               ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
               cmdStartInfo.FileName = @"C:\Windows\System32\cmd.exe";
               cmdStartInfo.RedirectStandardOutput = true;
               cmdStartInfo.RedirectStandardError = true;
               cmdStartInfo.RedirectStandardInput = true;
               cmdStartInfo.UseShellExecute = false;
               cmdStartInfo.CreateNoWindow = true;

               Process cmdProcess;
               //cmdProcess.StandardInput.WriteLine("Dism /online /disable-feature /featurename:IIS-FTPSvc /norestart");     //Execute command

               cmdProcess = new Process();
               cmdProcess.StartInfo = cmdStartInfo;
               cmdProcess.ErrorDataReceived += cmd_Error;
               cmdProcess.OutputDataReceived += cmd_SecurityZone_DataReceived;
               cmdProcess.EnableRaisingEvents = true;
               cmdProcess.Start();
               cmdProcess.BeginOutputReadLine();
               cmdProcess.BeginErrorReadLine();

               // turn prompts off
               cmdProcess.StandardInput.WriteLine(caspolApp + " -pp off");     //Execute command

               cmdProcess.StandardInput.WriteLine("exit");                  //Execute exit.

               cmdProcess.WaitForExit();
               cmdProcess.Close();

               if (!dotNetSecurityZoneSettingSuccessful)
               {
                  // 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(1);
                  msg = "\n" + indentation + "- FAILED. Access denied from running .NET Framework Caspol 2.0.";
                  UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);
                  ((frmSetupStatusDisplay)m_parentForm).displayMessageBox(MessageBoxCustom.PopUpMsgType.ERROR, null, "Access denied from running .NET Framework Caspol 2.0.\n\n Make sure to run application as Administrator...", "ERROR!!!", -1);
                  setupSuccessful = false;
               }

               foreach (string zone in securityZoneNames)
               {
                  cmdProcess = new Process();
                  cmdProcess.StartInfo = cmdStartInfo;
                  cmdProcess.ErrorDataReceived += cmd_Error;
                  cmdProcess.OutputDataReceived += cmd_SecurityZone_DataReceived;
                  cmdProcess.EnableRaisingEvents = true;
                  cmdProcess.Start();
                  cmdProcess.BeginOutputReadLine();
                  cmdProcess.BeginErrorReadLine();

                  dotNetSecurityZoneSettingSuccessful = false;

                  indentation = Common.getIndentation(1);
                  msg = "\n" + indentation + "" + zone + "=" + trustLevels[0];
                  UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

                  // set trust level for security zone
                  cmdProcess.StandardInput.WriteLine(caspolApp + " -m -cg " + zone + " " + trustLevels[0]);     //Execute command
                  //cmdProcess.StandardInput.WriteLine("");

                  //count++;

                  cmdProcess.StandardInput.WriteLine("exit");                  //Execute exit.

                  cmdProcess.WaitForExit();
                  cmdProcess.Close();

                  if (dotNetSecurityZoneSettingSuccessful)
                  {
                     // 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);

                     msg = " - SUCCESS";
                  }
                  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);

                     msg = " - FAILED";
                     setupSuccessful = false;
                  }

                  UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);
               }

               cmdProcess = new Process();
               cmdProcess.StartInfo = cmdStartInfo;
               //cmdProcess.ErrorDataReceived += cmd_Error;
               //cmdProcess.OutputDataReceived += cmd_SecurityZone_DataReceived;
               cmdProcess.EnableRaisingEvents = true;
               cmdProcess.Start();
               cmdProcess.BeginOutputReadLine();
               cmdProcess.BeginErrorReadLine();

               // turn policy change prompt back on. THIS IS VERY IMPORTANT
               // if this is not turned back on, the Windows Firewall might block some functionality of an application
               cmdProcess.StandardInput.WriteLine(caspolApp + " -pp on");     //Execute command

               cmdProcess.StandardInput.WriteLine("exit");                  //Execute exit.

               cmdProcess.WaitForExit();
               cmdProcess.Close();
            }
         }
         return setupSuccessful;
      }

      void cmd_SecurityZone_DataReceived(object sender, DataReceivedEventArgs e)
      {
         Match regExMatch;

         if (e.Data == null)
         {
            return;
         }

         regExMatch = Regex.Match(e.Data, @".*success.*", RegexOptions.IgnoreCase);
         if (regExMatch.Success)
         {
            dotNetSecurityZoneSettingSuccessful = true;
         }
      }

      void cmd_Error(object sender, DataReceivedEventArgs e)
      {
         //Console.WriteLine("Error from other process");
         //Console.WriteLine(e.Data);
      }
   }
}
