using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Xml;
using Microsoft.Win32;

namespace DecalUtil;

internal class Update
{
	private delegate int DllRegisterServerInvoker();

	private string updateUrl;

	private Queue<UpdateFile> files;

	public Update(string UpdateUrl)
	{
		updateUrl = UpdateUrl;
		files = new Queue<UpdateFile>();
	}

	public bool FetchUpdateList(IFormStatus status)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		XmlDocument val = new XmlDocument();
		WebClient webClient = new WebClient();
		try
		{
			val.Load(webClient.OpenRead(updateUrl));
			status.ReportStatus($"Parsing update list");
		}
		catch (WebException ex)
		{
			status.ReportStatus($"Error Occured: {ex.ToString()}");
			if (ex.Status == WebExceptionStatus.ProtocolError)
			{
				ex.Response.Close();
			}
			return false;
		}
		catch (Exception ex2)
		{
			status.ReportStatus($"Unknown Error Occured {ex2.ToString()}");
			return false;
		}
		webClient.Dispose();
		foreach (XmlNode item2 in ((XmlNode)val).SelectNodes("updatelist/file"))
		{
			XmlNode val2 = item2;
			string value = ((XmlNode)val2.Attributes["type"]).Value;
			string value2 = ((XmlNode)val2.Attributes["localname"]).Value;
			string value3 = ((XmlNode)val2.Attributes["remotename"]).Value;
			UpdateFile item = new UpdateFile(value, value2, value3);
			if (val2.Attributes["version"].Specified)
			{
				item.Version = ((XmlNode)val2.Attributes["version"]).Value;
			}
			files.Enqueue(item);
		}
		return true;
	}

	public void DownloadFiles(IFormStatus status)
	{
		string text = (string)Registry.LocalMachine.OpenSubKey("SOFTWARE\\Decal\\Agent").GetValue("AgentPath");
		status.Max = files.Count;
		status.Current = 0;
		status.ProgressEnabled = true;
		while (files.Count > 0)
		{
			UpdateFile updateFile = files.Dequeue();
			WebClient webClient = new WebClient();
			try
			{
				status.ReportStatus($"Fetching {updateFile.LocalName}");
				if (updateFile.Version == string.Empty || NewerVersion(updateFile.Version, updateFile.LocalName))
				{
					webClient.DownloadFile(updateFile.RemoteName, text + updateFile.LocalName);
				}
			}
			catch (WebException ex)
			{
				status.ReportStatus($"Failed to get file: {updateFile.LocalName}, {ex.ToString()}");
				if (ex.Status == WebExceptionStatus.ProtocolError)
				{
					ex.Response.Close();
				}
			}
			webClient.Dispose();
			status.Current++;
		}
		status.ReportStatus("Download Complete");
		status.ProgressEnabled = false;
	}

	private bool NewerVersion(string newVersion, string localFile)
	{
		FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(localFile);
		return string.Compare(newVersion, versionInfo.FileVersion, ignoreCase: true) > 0;
	}

	[DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)]
	private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

	[DllImport("kernel32.dll")]
	private static extern IntPtr LoadLibrary(string lpFileName);

	private void RegisterDll(string fileName)
	{
		try
		{
			((DllRegisterServerInvoker)Marshal.GetDelegateForFunctionPointer(GetProcAddress(LoadLibrary(fileName), "DllRegisterServer"), typeof(DllRegisterServerInvoker)))();
		}
		catch (Exception ex)
		{
			Console.WriteLine("Error Registering {0} -- {1}", fileName, ex.Message);
		}
	}
}
