using SolviaOneDriveKillerLib;
using SolviaOneDriveKillerLib.Entities;
using SolviaOneDriveKillerLib.Helpers;
using System.ComponentModel;
using System.IO;
using System.ServiceProcess;
using System.Timers;
using System.Xml.Serialization;

namespace SolviaOneDriveKiller
{
    public partial class MainService : ServiceBase
    {
        private static Timer mainTimer = new Timer();
        public const string JobFileJson = @"C:\solvia\job.json";
        public const string JobFileXml = @"C:\solvia\job.xml";

        protected BackgroundWorker worker;

        public MainService()
        {
            InitializeComponent();
        }

        internal void Start(string[] args)
        {
            OnStart(args);
        }

        protected override void OnStart(string[] args)
        {
            Logging.Log(Logging.LogLevel.Info, "OnStart called");
            //InitTimers();
            //StartTimers();

            worker = new BackgroundWorker
            {
                WorkerReportsProgress = false,
                WorkerSupportsCancellation = false
            };
            worker.DoWork += Worker_DoWork;
            worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
            worker.RunWorkerAsync();
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // This method is called when the background worker has finished its work.
            // You can handle any finalization here, such as logging completion or updating UI elements if applicable.
            Logging.Log(Logging.LogLevel.Info, "Background processing completed.");
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            Logging.SendToLog("Worker_DoWork called");
            Logging.SendToLog(@"Uninstalling OneDrive from C:\Windows\SysWOW64\OneDriveSetup.exe");

            var retCode = WindowsProcess.ExecuteCommand(@"C:\Windows\SysWOW64\OneDriveSetup.exe", "/uninstall", true);
            Logging.SendToLog($"done UninstallOneDrive -> Return Code: {retCode}");

            Logging.SendToLog($"Will remove {Constants.OneDriveExplorerTree} in machine context!");
            WindowsRegistry.DeleteRegistryEntry(Microsoft.Win32.RegistryHive.ClassesRoot, Constants.OneDriveExplorerTree);

            return;
            string s = WindowsRegistry.GetOneDriveUninstallStringMachine();

            if (string.IsNullOrEmpty(s))
            {
                Logging.SendToLog($"OneDrive not found in registry");
                return;
            }
            else
            {
                Logging.SendToLog($"OneDrive uninstall string: {s}");
                string path = HelperFunctions.ExtractPathFromCommandLine(s);
                Logging.SendToLog($"Path: {path}");
                string args = HelperFunctions.ExtractArgumentsFromCommandLine(s, path);
                Logging.SendToLog($"Args: {args}");
                var ret = WindowsProcess.ExecuteCommand(path, args + @" /silent", true);
                Logging.SendToLog($"UninstallOneDrive: {ret}");
            }


            //var ret = HelperFunctions.GetOneDriveSetups();

            //foreach (var item in ret)
            //{
            //    Logging.SendToLog($"{item.FileName} - {item.FileVersion}");
            //}

            //bool killProcRet = HelperFunctions.KillProcess("OneDrive");
            //Logging.SendToLog($"KillProcess: {killProcRet}");
            //HelperFunctions.UninstallOneDrive();
            //WindowsRegistry.DeleteOneDriveFromRegistry();
        }
        protected override void OnStop()
        {
            Logging.Log(Logging.LogLevel.Info, "OnStop called");
            mainTimer.Stop();
        }

        private void InitTimers()
        {
            int mainTimerValue = ConfigurationHelper.GetConfigValue<int>("MainTimerValue", 60000);
            Logging.Log(Logging.LogLevel.Info, $"MainTimerValue: {mainTimerValue}");

            mainTimer.Interval = mainTimerValue;
            mainTimer.Elapsed += new ElapsedEventHandler(MainTimerCallback);
            mainTimer.AutoReset = false;
            mainTimer.Enabled = true;
        }

        private void MainTimerCallback(object sender, ElapsedEventArgs e)
        {
            Logging.Log(Logging.LogLevel.Info, "MainTimerCallback called");

            if(File.Exists(JobFileXml))
            {
                try
                {
                    Logging.SendToLog($"found file: {JobFileXml}");
                    XmlSerializer serializer = new XmlSerializer(typeof(CustomCommand));
                    CustomCommand command = serializer.Deserialize(new FileStream(JobFileXml, FileMode.Open)) as CustomCommand;
                    Logging.SendToLog($"Command: {command.Command}, Arguments: {command.Arguments}");
                    var ret = WindowsProcess.ExecuteCommand(command.Command, command.Arguments, true);
                    Logging.SendToLog($"Command executed: {ret}");
                }
                catch (System.Exception ex)
                {
                    Logging.SendToLog($"An error occurred while trying to execute command from job.xml: {ex.Message}");
                }
                finally
                {
                    mainTimer.Start();
                }
            }
            else
            {
                Logging.Log(Logging.LogLevel.Info, $"file not found: {JobFileXml}");
            }

            if (File.Exists(JobFileJson))
            {
                try
                {
                    Logging.SendToLog($"found file: {JobFileJson}");
                    string json = File.ReadAllText(JobFileJson);
                    CustomCommand command = Newtonsoft.Json.JsonConvert.DeserializeObject<CustomCommand>(json);

                    Logging.SendToLog($"Command: {command.Command}");
                    Logging.SendToLog($"Arguments: {command.Arguments}");

                    Logging.SendToLog($"Command: {command.Command}, Arguments: {command.Arguments}");
                    var ret = WindowsProcess.ExecuteCommand(command.Command, command.Arguments, true);
                    Logging.SendToLog($"Command executed: {ret}");
                }
                catch (System.Exception ex)
                {
                    Logging.SendToLog($"An error occurred while trying to execute command from job.json: {ex.Message}");
                }
                finally
                {
                    //mainTimer.Start();
                }

            }
            else
            {
                Logging.Log(Logging.LogLevel.Info, $"file not found: {JobFileJson}");
            }
            mainTimer.Start();
        }

        private void StartTimers()
        {
            mainTimer.Start();
        }
    }
}