using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using QC.QsprShared.Dialogs;
using QC.QsprShared.Trace;

namespace QC.QTMApplication;

public class TreeConverter
{
	private string stylesheetfolder = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), QSPRMainWindow.FeatureConfigInfo.StyleSheetsDirectory);

	private string transformFileName = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), Path.Combine(QSPRMainWindow.FeatureConfigInfo.StyleSheetsDirectory, "TransformConfig.xml"));

	private string identityTransformFile = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), Path.Combine(QSPRMainWindow.FeatureConfigInfo.StyleSheetsDirectory, "Identity.xslt"));

	public static double QSPR_TREE_VERSION = 0.5;

	private string sourcefile;

	private string outputfile;

	private double version = -1.0;

	private string stylepath = Directory.GetParent(System.Windows.Forms.Application.StartupPath).FullName;

	public string OutputFile
	{
		get
		{
			return outputfile;
		}
		set
		{
			outputfile = value;
		}
	}

	public string SourceFile
	{
		get
		{
			return sourcefile;
		}
		set
		{
			sourcefile = value;
		}
	}

	public TreeConverter(string SourceFileName, string OutputFileName)
	{
		sourcefile = SourceFileName;
		outputfile = OutputFileName;
	}

	public TreeConverter(string SourceFileName)
	{
		TraceMessage.Write(ToString(), "TreeConverter constructor, SourceFileName: " + SourceFileName, TraceMessageType.Trace);
		sourcefile = SourceFileName;
		outputfile = SourceFileName;
	}

	public bool Convert()
	{
		TraceMessage.Write(ToString(), "TreeConverter.Convert()", TraceMessageType.Trace);
		try
		{
			if (version == -1.0)
			{
				version = GetTreeVersion();
			}
			ArrayList transformFileNames = GetTransformFileNames(version, transformFileName);
			ProcessTransform(transformFileNames, sourcefile, outputfile);
			RemoveRedundantContainers(outputfile);
			return true;
		}
		catch (Exception ex)
		{
			AppMessageDialog.Show("Failed to convert tree, Error: " + ex.Message, DialogResult.OK, MessageDialogType.Exception);
			TraceMessage.Write("Convert old tree ", ex.Message, TraceMessageType.Exception);
			return false;
		}
	}

	private void ProcessTransform(ArrayList al, string inputfilename, string outputfilename)
	{
		TraceMessage.Write(ToString(), "TreeConverter.ProcessTransform()", TraceMessageType.Trace);
		string inputfile = inputfilename;
		bool flag = true;
		foreach (string item in al)
		{
			flag = true;
			IdentityTransform(inputfile, out var identityfile);
			Transform(identityfile, Path.Combine(stylesheetfolder, item), outputfilename, flag);
			inputfile = outputfilename;
		}
	}

	private void RemoveRedundantContainers(string filename)
	{
		TraceMessage.Write(ToString(), "TreeConverter.RemoveRedundantContainers(), filename: " + filename, TraceMessageType.Trace);
		try
		{
			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.Load(filename);
			XmlNodeList xmlNodeList = null;
			xmlNodeList = xmlDocument.GetElementsByTagName("TestContainers");
			if (xmlNodeList != null && xmlNodeList.Count > 0)
			{
				Hashtable hashtable = new Hashtable(StringComparer.InvariantCultureIgnoreCase);
				ArrayList arrayList = new ArrayList();
				foreach (XmlNode item in xmlNodeList)
				{
					foreach (XmlNode childNode in item.ChildNodes)
					{
						if (childNode.Name == "Name")
						{
							if (!hashtable.Contains(childNode.InnerText))
							{
								hashtable.Add(childNode.InnerText, "");
							}
							else
							{
								arrayList.Add(item);
							}
							break;
						}
					}
				}
				foreach (object item2 in arrayList)
				{
					XmlNode xmlNode3 = (XmlNode)item2;
					xmlNode3.ParentNode.RemoveChild(xmlNode3);
				}
			}
			xmlDocument.Save(outputfile);
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "TreeConverter.RemoveRedundantContainers(), Exception: " + ex.Message, TraceMessageType.Exception);
		}
	}

	public double GetTreeVersion()
	{
		TraceMessage.Write(ToString(), "GetTreeVersion()", TraceMessageType.Trace);
		XmlDocument xmlDocument = new XmlDocument();
		xmlDocument.Load(sourcefile);
		XmlNodeList xmlNodeList = null;
		xmlNodeList = xmlDocument.GetElementsByTagName("TestTreeVersion");
		if (xmlNodeList.Count <= 0)
		{
			version = 1.0;
			if (sourcefile.Substring(sourcefile.Length - 3, 3).ToLower() == "xtt")
			{
				version = QSPR_TREE_VERSION;
				outputfile = sourcefile;
				return version;
			}
		}
		else
		{
			version = double.Parse(xmlNodeList.Item(0).InnerText, CultureInfo.InvariantCulture);
		}
		TraceMessage.Write(ToString(), "GetTreeVersion(), version returned: " + version, TraceMessageType.Trace);
		return version;
	}

	private ArrayList GetTransformFileNames(double version, string treeconfigfile)
	{
		TraceMessage.Write(ToString(), "TreeConverter.GetTransformFileNames(), version: " + version + ", treeconfigfile: " + treeconfigfile, TraceMessageType.Trace);
		ArrayList arrayList = new ArrayList();
		XmlDocument xmlDocument = new XmlDocument();
		xmlDocument.Load(treeconfigfile);
		XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName("Transform");
		double num = version;
		foreach (XmlNode item in elementsByTagName)
		{
			if (double.Parse(item.FirstChild.InnerText, CultureInfo.InvariantCulture) > num)
			{
				arrayList.Add(item.ChildNodes.Item(1).InnerText);
				if (item.ChildNodes.Count > 2)
				{
					num = int.Parse(item.ChildNodes.Item(2).InnerText);
				}
			}
		}
		return arrayList;
	}

	private bool IdentityTransform(string inputfile, out string identityfile)
	{
		TraceMessage.Write(ToString(), "TreeConverter.IdentityTransform(), inputfile: " + inputfile, TraceMessageType.Trace);
		XmlDocument xmlDocument = new XmlDocument();
		identityfile = Path.Combine(System.Windows.Forms.Application.UserAppDataPath, Process.GetCurrentProcess().Id + "_identityoutput.xml");
		XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
		XmlTextWriter xmlTextWriter = new XmlTextWriter(identityfile, null);
		try
		{
			xmlDocument.Load(inputfile);
			XmlElement documentElement = xmlDocument.DocumentElement;
			XPathNavigator input = documentElement.CreateNavigator();
			xslCompiledTransform.Load(identityTransformFile);
			xmlTextWriter.Formatting = Formatting.Indented;
			xslCompiledTransform.Transform(input, null, xmlTextWriter, null);
			xmlTextWriter.Close();
			return true;
		}
		catch (Exception ex)
		{
			TraceMessage.Write("IdentityTransform", ex.Message, TraceMessageType.Exception);
			identityfile = string.Empty;
			xmlTextWriter.Close();
			return false;
		}
	}

	private bool Transform(string inputfile, string transformfile, string outputfilename, bool DeleteInputFile)
	{
		TraceMessage.Write(ToString(), "TreeConverter.Transform(), inputfile: " + inputfile + ", transformfile: " + transformfile, TraceMessageType.Trace);
		if (!File.Exists(transformfile))
		{
			AppMessageDialog.Show("Error converting file, the transform file is missing:\n" + transformfile + "\nPlease re-install QSPR v" + System.Windows.Forms.Application.ProductVersion, "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Exception);
			return false;
		}
		if (File.Exists(outputfilename))
		{
			FileAttributes attributes = File.GetAttributes(outputfilename);
			if ((attributes & FileAttributes.ReadOnly) != 0)
			{
				DialogResult dialogResult = AppMessageDialog.Show(outputfilename + " is read only.\nDo you want to make the file writable?", "QSPR - Message Center", MessageBoxButtons.YesNo, MessageBoxIcon.Question, DialogResult.Yes, MessageDialogType.Warning);
				if (dialogResult != DialogResult.Yes)
				{
					return false;
				}
				try
				{
					File.SetAttributes(outputfilename, FileAttributes.Normal);
				}
				catch
				{
					AppMessageDialog.Show("Access denied for " + outputfilename, "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Exception);
					return false;
				}
			}
		}
		XmlDocument xmlDocument = new XmlDocument();
		XslCompiledTransform xslCompiledTransform = new XslCompiledTransform(enableDebug: true);
		XmlTextWriter xmlTextWriter = new XmlTextWriter(outputfilename, null);
		try
		{
			xmlDocument.Load(inputfile);
			XmlElement documentElement = xmlDocument.DocumentElement;
			documentElement.CreateNavigator();
			xslCompiledTransform.Load(transformfile);
			BitInfo extension = new BitInfo();
			TransformValues extension2 = new TransformValues();
			XsltArgumentList xsltArgumentList = new XsltArgumentList();
			xsltArgumentList.AddExtensionObject("urn:bitInfo", extension);
			xsltArgumentList.AddExtensionObject("urn:transformData", extension2);
			xmlTextWriter.Formatting = Formatting.Indented;
			xslCompiledTransform.Transform(inputfile, xsltArgumentList, xmlTextWriter);
			if (DeleteInputFile)
			{
				File.Delete(inputfile);
			}
			return true;
		}
		catch (Exception ex)
		{
			TraceMessage.Write("Transform", ex.Message, TraceMessageType.Exception);
			AppMessageDialog.Show("Exception in transforming " + inputfile + "\nwith " + transformfile + "\n " + ex.InnerException, "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Exception);
			return false;
		}
		finally
		{
			xmlTextWriter.Close();
		}
	}
}
