using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Data;
using VBNET = Microsoft.VisualBasic;
using gmRTL.Core;
using Microsoft.VisualBasic.CompilerServices;
using System.Linq;
using System.Collections.Generic;

namespace ScanToolLib
{
   public class clsScanControl
   {

      public class statusEventArgs : System.EventArgs
      {
         public string msg;
         public statusEventArgs(string msg)
         {
            this.msg = msg;
         }
      }
      public delegate void statusEventHandler(object sender,statusEventArgs e);
      public event System.EventHandler<statusEventArgs> status_Event;
      protected virtual void Onstatus_Event(string msg)
      {
         statusEventArgs e;
         if(status_Event != null)
         {
            e = new statusEventArgs(msg);
            status_Event?.Invoke(this,e);
         }
      }
      public string txtFolderFilter = "";
      public string txtFilFilter = "";
      public string txtContentFilter = "";
      public string txtSaveTo = "";
      public string txtRootPath = "";
      public string optRpt = "";
      public bool mfoldercnt = false;
      public bool chkNoCase = false;
      clsCOMReporter comReporter = null;
      clsVBPRefReporter vbpRefReporter = null;
      clsVBPBinReporter vbpBinReporter = null;
      clsVBPModReporter vbpModReporter = null;
      clsVBPSrcReporter vbpSrcReporter = null;
      clsVBPCntReporter vbpCntReporter = null;
      clsDirList dirLister = null;
      object filHandler = default;
      //  XML Config file constants

      private const string CFG_XMLDOC = "ScanTool";
      private const string CFG_ROOTPATH = "RootPath";
      private const string CFG_SAVETO = "SaveTo";
      private const string CFG_REPORT_MODE = "ReportMode";
      private const string CFG_FOLDER_FILTER = "FolderFilter";
      private const string CFG_FILE_FILTER = "FileFilter";
      private const string CFG_IGNORE_CASE = "IgnoreCase";
      private const string CFG_CONTENT_FILTER = "ContentFilter";
      private const string CFG_IGNORE_CASE_TRUE = "true";
      private const string CFG_IGNORE_CASE_FALSE = "false";
      public void runReport()
      {
         const string FUNC_NAME = "runReport";
         try
         {
            gmRTL.Core.GlobalException.Clear();

            report();

            setStatus(optRpt + " report successfully written to " + txtSaveTo);

         }
         catch(System.Exception exc)
         {
            gmRTL.Core.GlobalException.Initialize(exc);
         }

         if (gmRTL.Core.GlobalException.Instance.Number != 0)
         {
            setStatus("Completed with error " + this.GetTypeName() + "::" + FUNC_NAME + " " + "\r\n" + gmRTL.Core.GlobalException.Instance.Description);
         }
      }
      private void report()
      {
         const string FUNC_NAME = "report";
         System.IO.DirectoryInfo fld = null;
         System.IO.StreamWriter rpt = null;
         try
         {
            gmRTL.Core.GlobalException.Clear();

            if (txtRootPath == "")
            {
               gmRTL.Core.ErrorHandling.RaiseGlobalException(17,"Please set a root path",String.Empty);
            }

            setFileProcessor();


            fld = new System.IO.DirectoryInfo(txtRootPath);

            rpt = modScanToolLib.openOutputText(txtSaveTo);

            string[] dirPats = Array.Empty<string>();
            dirPats = txtFolderFilter.LCase().Split(",");

            string[] filPats = Array.Empty<string>();
            filPats = txtFilFilter.LCase().Split(",");

            if (mfoldercnt)
            {
               rpt.WriteLine("PATH" + "\t" + "SUBFOLDERS" + "\t" + "FILES" + "\t" + "SIZE");
               reportFolder(fld,rpt,dirPats,filPats);
            }
            else
            {
               rpt.WriteLine(((object)((dynamic)filHandler).header()).ToStr());
               reportFolder(fld,rpt,dirPats,filPats);
            }

            rpt.Close();

         }
         catch(System.Exception exc)
         {
            gmRTL.Core.GlobalException.Initialize(exc);
         }

         rpt = null;
         fld = null;

         if (gmRTL.Core.GlobalException.Instance.Number != 0)
         {
            gmRTL.Core.ErrorHandling.RaiseGlobalException(gmRTL.Core.GlobalException.Instance.Number,String.Empty,this.GetTypeName() + "::" + FUNC_NAME + " " + "\r\n" + gmRTL.Core.GlobalException.Instance.Description);
         }

      }
      private void reportFolder(System.IO.DirectoryInfo fld,System.IO.StreamWriter rpt,string[] dirPats,string[] filPats)
      {
         const string FUNC_NAME = "reportFolder";
         System.IO.FileInfo fil = null;
         System.IO.DirectoryInfo subfld = null;
         try
         {
            gmRTL.Core.GlobalException.Clear();

            int i = 0;
            int filPatCnt = 0;
            filPatCnt = filPats.GetUpperBound(0);
            int dirPatCnt = 0;
            dirPatCnt = dirPats.GetUpperBound(0);

            string fldpath = "";
            fldpath = fld.FullName.LCase() + "\\";
            setStatus(fldpath);

            bool scanDir = false;
            for(i = 0; i <= dirPatCnt; i += 1)
            {
               scanDir = fldpath.Like(dirPats[i]);
               if (scanDir)
               {
                  break;  // Exit For
               }
            }

            if (scanDir)
            {

               int filCnt = 0;
               filCnt = 0;
               double filSiz = 0.0;
               filSiz = 0;

               foreach(System.IO.FileInfo forTemp0 in fld.GetFiles())
               {
                  fil = forTemp0;

                  string filname = "";
                  filname = fil.Name.LCase();

                  bool scanFil = false;
                  for(i = 0; i <= filPatCnt; i += 1)
                  {
                     scanFil = filname.Like(filPats[i]);
                     if (scanFil)
                     {
                        break;  // Exit For
                     }
                  }

                  if (scanFil)
                  {

                     setStatus(fil.FullName);

                     if (mfoldercnt)
                     {
                        filCnt = filCnt + 1;
                        filSiz = filSiz + fil.Length;
                     }
                     else
                     {
                        ((dynamic)filHandler).processFile(fil,rpt);
                     }

                  }

               }

               if (mfoldercnt)
               {

                  modScanToolLib.writeRpt(rpt,fld.FullName + "\t" + fld.GetDirectories().Length + "\t" + filCnt + "\t" + filSiz.ToStr() + "\r\n");
               }

            }

            //  recurse through all subfolders

            foreach(System.IO.DirectoryInfo forTemp1 in fld.GetDirectories())
            {
               subfld = forTemp1;
               reportFolder(subfld,rpt,dirPats,filPats);
            }

         }
         catch(System.Exception exc)
         {
            gmRTL.Core.GlobalException.Initialize(exc);
         }

         subfld = null;
         fil = null;

         if (gmRTL.Core.GlobalException.Instance.Number != 0)
         {
            gmRTL.Core.ErrorHandling.RaiseGlobalException(gmRTL.Core.GlobalException.Instance.Number,String.Empty,this.GetTypeName() + "::" + FUNC_NAME + " " + "\r\n" + gmRTL.Core.GlobalException.Instance.Description);
         }
      }
      private void setStatus(string msg)
      {
         Onstatus_Event(msg);
      }
      public void setParms()
      {

         switch(optRpt)
         {
         case "DirList":
            txtFolderFilter = "*";
            txtFilFilter = "*";
            txtContentFilter = "";
            break;
         case "COMGuid":
            txtFolderFilter = "*";
            txtFilFilter = "*.ocx,*.exe,*.dll,*.olb,*.tlb";
            break;
         case "VBPRef":
            txtFolderFilter = "*";
            txtFilFilter = "*.vbp";
            break;
         case "VBPBin":
            txtFolderFilter = "*";
            txtFilFilter = "*.vbp";
            break;
         case "VBPMod":
            txtFolderFilter = "*";
            txtFilFilter = "*.vbp";
            break;
         case "VBPSource":
            txtFolderFilter = "*";
            txtFilFilter = "*.vbp";
            break;
         case "VBPCount":
            txtFolderFilter = "*";
            txtFilFilter = "*.vbp";
            break;
         case "FolderCnt":
            txtFolderFilter = "*";
            txtFilFilter = "*";
            break;
         default:
            gmRTL.Core.ErrorHandling.RaiseGlobalException(17,String.Empty,"Unknown mode " + optRpt);
            break;
         }

         txtSaveTo = optRpt + ".tdf";

      }
      public void setFileProcessor()
      {
         mfoldercnt = false;
         switch(optRpt)
         {
         case "DirList":
            dirLister = new clsDirList();
            dirLister.contentFilter = txtContentFilter;
            dirLister.noCase = chkNoCase;
            filHandler = dirLister;
            break;
         case "COMGuid":
            comReporter = new clsCOMReporter();
            filHandler = comReporter;
            break;
         case "VBPRef":
            vbpRefReporter = new clsVBPRefReporter();
            filHandler = vbpRefReporter;
            break;
         case "VBPBin":
            vbpBinReporter = new clsVBPBinReporter();
            filHandler = vbpBinReporter;
            break;
         case "VBPMod":
            vbpModReporter = new clsVBPModReporter();
            filHandler = vbpModReporter;
            break;
         case "VBPSource":
            vbpSrcReporter = new clsVBPSrcReporter();
            filHandler = vbpSrcReporter;
            break;
         case "VBPCount":
            vbpCntReporter = new clsVBPCntReporter();
            filHandler = vbpCntReporter;
            break;
         case "FolderCnt":
            mfoldercnt = true;
            break;
         }
      }
      public string Show()
      {
         string rpt = "";
         rpt = rpt + "optRpt           = [" + optRpt + "]" + "\r\n";
         rpt = rpt + "txtFolderFilter  = [" + txtFolderFilter + "]" + "\r\n";
         rpt = rpt + "txtFilFilter     = [" + txtFilFilter + "]" + "\r\n";
         rpt = rpt + "txtContentFilter = [" + txtContentFilter + "]" + "\r\n";
         rpt = rpt + "txtSaveTo        = [" + txtSaveTo + "]" + "\r\n";
         rpt = rpt + "txtRootPath      = [" + txtRootPath + "]" + "\r\n";
         rpt = rpt + "mfoldercnt       = [" + mfoldercnt.ToStr() + "]" + "\r\n";
         rpt = rpt + "chkNoCase        = [" + chkNoCase.ToStr() + "]" + "\r\n";
         return rpt;
      }
      public void loadScantoolConfig(string filename)
      {
         const string FUNC_NAME = "loadScantoolConfig";
         System.Xml.XmlDocument domConfig = null;
         try
         {
            gmRTL.Core.GlobalException.Clear();

            domConfig = new System.Xml.XmlDocument();

            try{
               domConfig.Load(filename);
            }catch{}
            if (!domConfig.HasChildNodes)
            {
               gmRTL.Core.ErrorHandling.RaiseGlobalException(17,this.GetTypeName(),"Unable to load XML documentt: " + filename);
            }


            System.Diagnostics.Debug.WriteLine(domConfig.InnerXml);

            this.txtSaveTo = modScanToolLib.readNode(domConfig,"//" + CFG_XMLDOC + "//" + CFG_SAVETO);
            this.txtRootPath = modScanToolLib.readNode(domConfig,"//" + CFG_XMLDOC + "//" + CFG_ROOTPATH);
            this.txtFilFilter = modScanToolLib.readNode(domConfig,"//" + CFG_XMLDOC + "//" + CFG_FILE_FILTER);
            this.txtFolderFilter = modScanToolLib.readNode(domConfig,"//" + CFG_XMLDOC + "//" + CFG_FOLDER_FILTER);
            this.txtContentFilter = modScanToolLib.readNode(domConfig,"//" + CFG_XMLDOC + "//" + CFG_CONTENT_FILTER);
            this.optRpt = modScanToolLib.readNode(domConfig,"//" + CFG_XMLDOC + "//" + CFG_REPORT_MODE);
            this.chkNoCase = modScanToolLib.readNode(domConfig,"//" + CFG_XMLDOC + "//" + CFG_CONTENT_FILTER + "//@" + CFG_IGNORE_CASE) == CFG_IGNORE_CASE_TRUE;

         }
         catch(System.Exception exc)
         {
            gmRTL.Core.GlobalException.Initialize(exc);
         }

         domConfig = null;

         if (gmRTL.Core.GlobalException.Instance.Number != 0)
         {
            gmRTL.Core.ErrorHandling.RaiseGlobalException(gmRTL.Core.GlobalException.Instance.Number,String.Empty,this.GetTypeName() + "::" + FUNC_NAME + " " + "\r\n" + gmRTL.Core.GlobalException.Instance.Description);
         }
      }
      public void saveScantoolConfig(string filename)
      {
         const string FUNC_NAME = "saveScantoolConfig";
         System.Xml.XmlDocument domConfig = null;
         try
         {
            gmRTL.Core.GlobalException.Clear();

            domConfig = new System.Xml.XmlDocument();

            System.Xml.XmlElement elmRoot = null;

            elmRoot = domConfig.CreateElement(CFG_XMLDOC);
            domConfig.AppendChild(elmRoot);

            System.Xml.XmlElement elmParam = null;

            elmParam = modScanToolLib.writeTextNode(elmRoot,CFG_ROOTPATH,txtRootPath);
            elmParam = modScanToolLib.writeTextNode(elmRoot,CFG_REPORT_MODE,optRpt);
            elmParam = modScanToolLib.writeTextNode(elmRoot,CFG_SAVETO,txtSaveTo);
            elmParam = modScanToolLib.writeTextNode(elmRoot,CFG_FILE_FILTER,txtFilFilter);
            elmParam = modScanToolLib.writeTextNode(elmRoot,CFG_FOLDER_FILTER,txtFolderFilter);
            elmParam = modScanToolLib.writeTextNode(elmRoot,CFG_CONTENT_FILTER,txtContentFilter);
            elmParam.SetAttribute(CFG_IGNORE_CASE,(chkNoCase ? CFG_IGNORE_CASE_TRUE : CFG_IGNORE_CASE_FALSE));

            System.Diagnostics.Debug.WriteLine(domConfig.InnerXml);

            domConfig.Save(filename);

         }
         catch(System.Exception exc)
         {
            gmRTL.Core.GlobalException.Initialize(exc);
         }

         domConfig = null;

         if (gmRTL.Core.GlobalException.Instance.Number != 0)
         {
            gmRTL.Core.ErrorHandling.RaiseGlobalException(gmRTL.Core.GlobalException.Instance.Number,String.Empty,this.GetTypeName() + "::" + FUNC_NAME + " " + "\r\n" + gmRTL.Core.GlobalException.Instance.Description);
         }
      }
   }
}
