using System;
using System.Collections.Generic;
using System.ComponentModel;
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 System.Xml;
using System.Xml.XPath;
using System.Net;

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

namespace All_Purpose_Auto_Setup
{
   class FileFolderRemovalManager
   {
      // 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 event Action<string, int, List<CommonLib.Windows.Forms.TextFormat.TextFontAndColor>> UpdateStatusDisplayAtLine;

      public List<ConfigFileManager.Ini_KeyValue<bool>> filesFoldersToBeRemoved = new List<ConfigFileManager.Ini_KeyValue<bool>>();

      Form m_parentForm;

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

      public bool removeFilesFolders(string sectionName)
      {
         bool setupSuccessful = true;
         string msg, indentation = String.Empty, displayMsg = "", logMsg = "";

         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 = 10;
         // 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-=Removing Files/Folders=-";
         UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);

         filesFoldersToBeRemoved.Clear();

         parseConfigInfo(sectionName);

         if (setupSuccessful)
         {
            int filesDeletedCount = 0, foldersDeletedCount = 0, filesSkipped = 0, foldersSkipped = 0;
            frmSetupStatusDisplay displayFrm = (frmSetupStatusDisplay)m_parentForm;
            int itemCountLineIndex = displayFrm.updateStatusDisplayAndLog("\n  ", "", textPropList);
            int deleteItemLineIndex = displayFrm.updateStatusDisplayAndLog("\n  ", "", textPropList);

            List<string> filesAndFoldersToBeRemoved = new List<string>();

            foreach (ConfigFileManager.Ini_KeyValue<bool> item in filesFoldersToBeRemoved)
            {
               string path = "";
               path = Path.GetFullPath(Common.resolveMacroPath(item.iniValue));

               if (File.Exists(path))
               {
                  filesAndFoldersToBeRemoved.Add(path);
               }
               else if (Directory.Exists(path))
               {
                  // delete folder recursively
                  if (item.alternateValue)
                  {
                     filesAndFoldersToBeRemoved.Add(path);
                  }
                  else
                  {
                     string[] files = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly);
                     filesAndFoldersToBeRemoved.AddRange(files.ToList());
                  }
               }
               else
               {
                  string what = "";

                  if (PathManip.PathIsFile(path))
                  {
                     filesSkipped++;
                     what = "File";
                  }
                  else
                  {
                     foldersSkipped++;
                     what = "Folder";
                  }

                  indentation = Common.getIndentation(1);
                  logMsg = "\n" + indentation + "Deleting " + path + " - SKIPPED. " + what + " does not exist";
                  UpdateStatusDisplayAndLogEvent("", logMsg, textPropList);
               }

            }

            foreach (string item in filesAndFoldersToBeRemoved)
            {
               indentation = Common.getIndentation(1);
               msg = indentation + "Files Deleted: " + filesDeletedCount.ToString() + "     Folders Deleted: " + foldersDeletedCount.ToString();

               // set font to default text and color
               textProp.textFont = defaultTextProp.textFont;
               textProp.textColor = Color.FromArgb(5, 112, 1);
               textProp.wordIndex = 0;
               textProp.wordCount = 2;
               // set font style
               textPropList.Add(textProp);

               // set font to default text and color
               textProp.textFont = defaultTextProp.textFont;
               textProp.textColor = Color.FromArgb(5, 112, 1);
               textProp.wordIndex = 2;
               textProp.wordCount = 1;
               // set font style
               textProp.textFont = new Font(textProp.textFont.FontFamily, 10, FontStyle.Bold);
               textPropList.Add(textProp);

               // set font to default text and color
               textProp.textFont = defaultTextProp.textFont;
               textProp.textColor = Color.FromArgb(5, 112, 1);
               textProp.wordIndex = StringManip.GetPhraseWordIndexInText(msg, "Folders deleted:");
               textProp.wordCount = 2;
               textPropList.Add(textProp);

               // set font to default text and color
               textProp.textFont = defaultTextProp.textFont;
               textProp.textColor = Color.FromArgb(5, 112, 1);
               textProp.wordIndex = StringManip.GetPhraseWordIndexInText(msg, "Folders deleted:") + 2;
               textProp.wordCount = 1;
               // set font style
               textProp.textFont = new Font(textProp.textFont.FontFamily, 10, FontStyle.Bold);
               textPropList.Add(textProp);

               UpdateStatusDisplayAtLine(msg, itemCountLineIndex, textPropList);

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

               if (File.Exists(item) || Directory.Exists(item))
               {
                  displayMsg = indentation + "Deleting " + StringManip.ShortenStringToSize(item, 65);

                  // set font to default text and color
                  textProp.textFont = defaultTextProp.textFont;
                  //textProp.textColor = Color.FromArgb(157, 150, 19);
                  textProp.wordIndex = 0;
                  textProp.wordCount = 1;
                  textPropList.Add(textProp);

                  // set font to default text and color
                  textProp.textFont = defaultTextProp.textFont;
                  textProp.textColor = Color.FromArgb(255, 60, 0);
                  textProp.wordIndex = 1;
                  textProp.wordCount = 100;
                  // set font style
                  textProp.textFont = new Font(textProp.textFont, FontStyle.Bold);
                  textPropList.Add(textProp);

                  UpdateStatusDisplayAtLine(displayMsg, deleteItemLineIndex, textPropList);

                  if (Directory.Exists(item))
                  {
                     try
                     {
                        PathManip.DeleteFoldersRecursive(item);
                        foldersDeletedCount++;
                        logMsg = "\n" + indentation + "Deleting " + item + " - SUCCESS";
                     }
                     catch (Exception e)
                     {
                        // 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);

                        displayMsg = "\n" + indentation + "- FAILED. Error deleting folder\n" + indentation + "Folder: " + item + "\n" + indentation + "Error description: " + e.Message;
                        logMsg = "\n" + indentation + "Deleting " + item + " - FAILED";
                        setupSuccessful = false;
                     }
                  }
                  else
                  {
                     try
                     {
                        File.SetAttributes(item, FileAttributes.Normal);
                        File.Delete(item);
                        filesDeletedCount++;
                        logMsg = "\n" + indentation + "Deleting " + item + " - SUCCESS";
                     }
                     catch (Exception e)
                     {
                        // 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);

                        displayMsg = "\n" + indentation + "- FAILED. Error deleting file\n" + indentation + "File: " + item + "\n" + indentation + "Error description: " + e.Message;
                        logMsg = "\n" + indentation + "Deleting " + item + " - FAILED";
                        setupSuccessful = false;
                     }
                  }

                  if (!setupSuccessful)
                  {
                     break;
                  }

                  UpdateStatusDisplayAndLogEvent("", logMsg, textPropList);
               }

               Thread.Sleep(2000);
            }

            // delete the very first line that is the start of the progress update
            // all the lines below the first starting lines will get deleted too
            for (int i = 1; i <= 2; i++)
            {
               displayFrm.removeStatusDisplayLine(itemCountLineIndex, true);
            }

            if (!setupSuccessful)
            {
               UpdateStatusDisplayAndLogEvent(displayMsg, logMsg, textPropList);
            }

            if (setupSuccessful)
            {
               if (filesFoldersToBeRemoved.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 file/folder to delete";
                  UpdateStatusDisplayAndLogEvent(msg, msg, textPropList);
               }
               else
               {
                  // 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(1);
                  msg = "\n" + indentation + "- SUCCESS. (Files Deleted: " + filesDeletedCount + " ) (Folders Deleted: " + foldersDeletedCount + " )" + " (Files skipped: " + filesSkipped + " )" + " (Folders skipped: " + foldersSkipped + " )";
                  UpdateStatusDisplayAndLogEvent(msg, "", textPropList);
               }
            }

            msg = "\n" + Common.getIndentation(1) + "Files Deleted: " + filesDeletedCount + "   |   Folders Deleted: " + foldersDeletedCount + "   |   Files Skipped: " + filesSkipped + "   |   Folders Skipped: " + foldersSkipped;
            UpdateStatusDisplayAndLogEvent("", msg, textPropList);

         }

         return setupSuccessful;
      }

      private void parseConfigInfo(string sectionName)
      {
         string[] keyDataPair;
         Match regExMatch;
         ConfigFileManager.Ini_KeyValue<bool> bIniVal = new ConfigFileManager.Ini_KeyValue<bool>(false);

         string[] sectionData;

         sectionData = ConfigFileManager.ms_configGeneralInfo.iniFile.ReadSectionData(sectionName);

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

            if (keyDataPair.Length == 2)
            {
               bIniVal.iniSectionName = sectionName;
               bIniVal.iniKeyName = keyDataPair[0];
               bIniVal.iniValue = keyDataPair[1];

               regExMatch = Regex.Match(bIniVal.iniValue, @"^([^,]+),.*recursive.*", RegexOptions.IgnoreCase);

               if (regExMatch.Success)
               {
                  bIniVal.alternateValue = true;
                  bIniVal.iniValue = regExMatch.Groups[1].Value;
               }
               else
                  bIniVal.alternateValue = false;

               filesFoldersToBeRemoved.Add(bIniVal);
            }
         }
      }
   }
}
