using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Reflection;
using System.Windows.Forms;
using QCRPG.Framework;

namespace QCRPG.TSL.FMHCI;

public class FMHCIGooier : GooierBase, QCRPG.Framework.IObserver<ConnectionStateChangeInfo>
{
	protected enum ControlEnableMode
	{
		DEFAULT,
		CONNECTION_OPENED,
		CONNECTION_CLOSED
	}

	protected const string menuTextOpenConnection = "Open Connection";

	protected const string menuTextCloseConnection = "Close Connection";

	protected const string menuTextLoadDefaultNVMFile = "Load Default NVM File";

	protected const string menuTextLoadNVMFile = "Load NVM File";

	protected const string menuTextLoadDefaultPatchFile = "Load Default Patch File";

	protected const string menuTextLoadPatchFile = "Load Patch File";

	protected const string menuTextLoadDefaultSpurTableFile = "Load Default Spur Table File";

	protected const string menuTextLoadSpurTableFile = "Load Spur Table File";

	protected Configurer configurer;

	protected FMHCIAPI fmhciAPI;

	protected PacketListBase packetList;

	protected PacketUserControl packetUserControl;

	protected FMHCIMainWorkerThread fmhciMainWorkerThread;

	protected ToolStripButton toolStripButtonOpenConnection;

	protected ToolStripButton toolStripButtonCloseConnection;

	protected ToolStripButton toolStripButtonLoadDefaultNvm;

	protected ToolStripButton toolStripButtonLoadNvm;

	protected ToolStripButton toolStripButtonLoadDefaultPatch;

	protected ToolStripButton toolStripButtonLoadPatch;

	protected ToolStripButton toolStripButtonLoadDefaultSpurTable;

	protected ToolStripButton toolStripButtonLoadSpurTable;

	protected bool nvmInitialDirectorySet;

	protected bool patchInitialDirectorySet;

	protected bool spurTableInitialDirectorySet;

	protected OpenConnectionPortRateForm openConnectionPortRateForm = new OpenConnectionPortRateForm();

	protected FMHCIConfigUserControl fmhciConfigUserControl;

	protected FMHCIConfigSettings fmhciConfigSettings;

	protected bool deviceEmulationMode;

	protected DeviceEmulationModeUserControl deviceEmulationModeUserControl;

	protected DeviceEmulationModeConfigSettings deviceEmulationModeConfigSettings;

	protected PacketAutoResponder packetAutoResponder;

	public FMHCIGooier(string technologyName, Logger logger, Configurer configurer, FMHCIAPI fmhciAPI, PacketListBase packetList, FMHCIConfigSettings fmhciConfigSettings, FMHCIMainWorkerThread fmhciMainWorkerThread, bool deviceEmulationMode, DeviceEmulationModeConfigSettings deviceEmulationModeConfigSettings, PacketAutoResponder packetAutoResponder)
		: base(technologyName, logger)
	{
		this.configurer = configurer;
		this.fmhciAPI = fmhciAPI;
		this.packetList = packetList;
		this.fmhciConfigSettings = fmhciConfigSettings;
		this.fmhciMainWorkerThread = fmhciMainWorkerThread;
		this.deviceEmulationMode = deviceEmulationMode;
		this.packetAutoResponder = packetAutoResponder;
		if (!deviceEmulationMode)
		{
			packetUserControl = new PacketUserControl(packetList.CommandPackets);
		}
		else
		{
			List<PacketBase> list = new List<PacketBase>();
			list.AddRange(packetList.ResponsePackets);
			list.AddRange(packetList.NotificationPackets);
			packetUserControl = new PacketUserControl(list);
			this.deviceEmulationModeConfigSettings = deviceEmulationModeConfigSettings;
			deviceEmulationModeUserControl = new DeviceEmulationModeUserControl(deviceEmulationModeConfigSettings, packetAutoResponder);
		}
		packetUserControl.RegisterLogMessageObserver(logger);
		configurer.RegisterConfigurableObject(openConnectionPortRateForm, "OpenConnectionPortRateFormSettings");
		fmhciConfigUserControl = new FMHCIConfigUserControl(fmhciConfigSettings);
	}

	protected override void StartupComplete()
	{
		SetControlEnables(ControlEnableMode.DEFAULT);
		fmhciAPI.RegisterConnectionStateChangeInfoObserver(this);
	}

	public void ApplicationReady()
	{
		if (fmhciConfigSettings.OpenFMHCIConnectionOnStartup)
		{
			string selectedPortName = openConnectionPortRateForm.SelectedPortName;
			int selectedDataRate = openConnectionPortRateForm.SelectedDataRate;
			Handshake serialSelectedHandShake = openConnectionPortRateForm.SerialSelectedHandShake;
			try
			{
				fmhciAPI.OpenConnection(selectedPortName, selectedDataRate, serialSelectedHandShake);
			}
			catch (Exception ex)
			{
				logger.Enqueue(new LogMessage(LogMessageType.Error, ex));
			}
		}
	}

	protected override void AddUserControls()
	{
		userControls.Add(packetUserControl);
		userControls.Add(fmhciConfigUserControl);
		configurer.RegisterConfigurableObject(packetUserControl, "PacketUserControlSettings");
		configurer.RegisterConfigurableObject(fmhciConfigUserControl, "FMHCIConfigUserControlSettings");
		if (deviceEmulationMode)
		{
			userControls.Add(deviceEmulationModeUserControl);
			configurer.RegisterConfigurableObject(deviceEmulationModeUserControl, "DeviceEmulationModeUserControlSettings");
		}
	}

	protected override void BuildDropDownMenu()
	{
		dropDownMenu.Text = technologyName;
		AddDropDownMenuItems();
		SetDropDownMenuItemNames();
	}

	protected void AddDropDownMenuItems()
	{
		dropDownMenu.DropDownItems.Add("Open Connection", null, OpenConnectionHandler);
		dropDownMenu.DropDownItems.Add("Close Connection", null, CloseConnectionHandler);
		dropDownMenu.DropDownItems.Add("Load Default NVM File", null, LoadDefaultNvmHandler);
		dropDownMenu.DropDownItems.Add("Load NVM File", null, LoadNvmHandler);
		dropDownMenu.DropDownItems.Add("Load Default Patch File", null, LoadDefaultPatchHandler);
		dropDownMenu.DropDownItems.Add("Load Patch File", null, LoadPatchHandler);
		dropDownMenu.DropDownItems.Add("Load Default Spur Table File", null, LoadDefaultSpurTableHandler);
		dropDownMenu.DropDownItems.Add("Load Spur Table File", null, LoadSpurTableHandler);
	}

	protected void SetDropDownMenuItemNames()
	{
		for (int i = 0; i < dropDownMenu.DropDownItems.Count; i++)
		{
			dropDownMenu.DropDownItems[i].Name = dropDownMenu.DropDownItems[i].Text;
		}
	}

	protected override void BuildCustomToolStrip()
	{
		toolStripButtonOpenConnection = new ToolStripButton(Resources.GetImage("OpenConnection.png"));
		toolStripButtonOpenConnection.DisplayStyle = ToolStripItemDisplayStyle.Image;
		toolStripButtonOpenConnection.AutoToolTip = true;
		toolStripButtonOpenConnection.ToolTipText = "Open a FM HCI connection";
		toolStripButtonOpenConnection.Click += OpenConnectionHandler;
		customToolStripItems.Add(toolStripButtonOpenConnection);
		toolStripButtonCloseConnection = new ToolStripButton(Resources.GetImage("CloseConnection.png"));
		toolStripButtonCloseConnection.DisplayStyle = ToolStripItemDisplayStyle.Image;
		toolStripButtonCloseConnection.AutoToolTip = true;
		toolStripButtonCloseConnection.ToolTipText = "Close a FM HCI connection";
		toolStripButtonCloseConnection.Click += CloseConnectionHandler;
		customToolStripItems.Add(toolStripButtonCloseConnection);
		toolStripButtonLoadDefaultNvm = new ToolStripButton(Resources.GetImage("LoadDefaultNvm.png"));
		toolStripButtonLoadDefaultNvm.DisplayStyle = ToolStripItemDisplayStyle.Image;
		toolStripButtonLoadDefaultNvm.AutoToolTip = true;
		toolStripButtonLoadDefaultNvm.ToolTipText = "Load the default FM HCI NVM file specified in the config";
		toolStripButtonLoadDefaultNvm.Click += LoadDefaultNvmHandler;
		customToolStripItems.Add(toolStripButtonLoadDefaultNvm);
		toolStripButtonLoadNvm = new ToolStripButton(Resources.GetImage("LoadNvm.png"));
		toolStripButtonLoadNvm.DisplayStyle = ToolStripItemDisplayStyle.Image;
		toolStripButtonLoadNvm.AutoToolTip = true;
		toolStripButtonLoadNvm.ToolTipText = "Choose and load an FM HCI NVM file";
		toolStripButtonLoadNvm.Click += LoadNvmHandler;
		customToolStripItems.Add(toolStripButtonLoadNvm);
		toolStripButtonLoadDefaultPatch = new ToolStripButton(Resources.GetImage("LoadDefaultPatch.png"));
		toolStripButtonLoadDefaultPatch.DisplayStyle = ToolStripItemDisplayStyle.Image;
		toolStripButtonLoadDefaultPatch.AutoToolTip = true;
		toolStripButtonLoadDefaultPatch.ToolTipText = "Load the default FM HCI firmware patch file specified in the config";
		toolStripButtonLoadDefaultPatch.Click += LoadDefaultPatchHandler;
		customToolStripItems.Add(toolStripButtonLoadDefaultPatch);
		toolStripButtonLoadPatch = new ToolStripButton(Resources.GetImage("LoadPatch.png"));
		toolStripButtonLoadPatch.DisplayStyle = ToolStripItemDisplayStyle.Image;
		toolStripButtonLoadPatch.AutoToolTip = true;
		toolStripButtonLoadPatch.ToolTipText = "Choose and load an FM HCI firmware patch file";
		toolStripButtonLoadPatch.Click += LoadPatchHandler;
		customToolStripItems.Add(toolStripButtonLoadPatch);
		toolStripButtonLoadDefaultSpurTable = new ToolStripButton(Resources.GetImage("LoadDefaultSpurTable.png"));
		toolStripButtonLoadDefaultSpurTable.DisplayStyle = ToolStripItemDisplayStyle.Image;
		toolStripButtonLoadDefaultSpurTable.AutoToolTip = true;
		toolStripButtonLoadDefaultSpurTable.ToolTipText = "Load the default FM HCI spur table file specified in the config";
		toolStripButtonLoadDefaultSpurTable.Click += LoadDefaultSpurTableHandler;
		customToolStripItems.Add(toolStripButtonLoadDefaultSpurTable);
		toolStripButtonLoadSpurTable = new ToolStripButton(Resources.GetImage("LoadSpurTable.png"));
		toolStripButtonLoadSpurTable.DisplayStyle = ToolStripItemDisplayStyle.Image;
		toolStripButtonLoadSpurTable.AutoToolTip = true;
		toolStripButtonLoadSpurTable.ToolTipText = "Choose and load an FM HCI spur table file";
		toolStripButtonLoadSpurTable.Click += LoadSpurTableHandler;
		customToolStripItems.Add(toolStripButtonLoadSpurTable);
	}

	private void OpenConnectionHandler(object sender, EventArgs e)
	{
		openConnectionPortRateForm.Title = "Open FM HCI Connection";
		openConnectionPortRateForm.DisplayedDataRateList = new List<int>
		{
			300, 1200, 2400, 4800, 9600, 19200, 34800, 57600, 115200, 3000000,
			3200000
		};
		if (openConnectionPortRateForm.ShowDialog() != DialogResult.OK)
		{
			return;
		}
		string selectedPortName = openConnectionPortRateForm.SelectedPortName;
		int selectedDataRate = openConnectionPortRateForm.SelectedDataRate;
		Handshake serialSelectedHandShake = openConnectionPortRateForm.SerialSelectedHandShake;
		bool sharedConnectionEnabled = openConnectionPortRateForm.SharedConnectionEnabled;
		try
		{
			if (sharedConnectionEnabled)
			{
				if (!APIBase.IsSharedConnectionActiveAndOpen(selectedPortName))
				{
					APIBase.OpenNewSharedSerialConnection(selectedPortName, selectedDataRate, serialSelectedHandShake);
				}
				fmhciAPI.AddToSharedSerialConnection(selectedPortName);
			}
			else
			{
				fmhciAPI.OpenConnection(selectedPortName, selectedDataRate, serialSelectedHandShake);
			}
		}
		catch (Exception ex)
		{
			logger.Enqueue(new LogMessage(LogMessageType.Error, ex));
			MessageBoxes.ShowErrorBox("Error opening FM HCI serial connection");
			return;
		}
		SetControlEnables(ControlEnableMode.CONNECTION_OPENED);
	}

	private void CloseConnectionHandler(object sender, EventArgs e)
	{
		try
		{
			string selectedPortName = openConnectionPortRateForm.SelectedPortName;
			if (openConnectionPortRateForm.SharedConnectionEnabled)
			{
				APIBase.CloseSharedSerialConnection(selectedPortName);
			}
			else
			{
				fmhciAPI.CloseConnection();
			}
		}
		catch (Exception ex)
		{
			logger.Enqueue(new LogMessage(LogMessageType.Error, ex));
			MessageBoxes.ShowErrorBox("Error closing FM HCI connection");
			SetControlEnables(ControlEnableMode.CONNECTION_CLOSED);
			return;
		}
		SetControlEnables(ControlEnableMode.CONNECTION_CLOSED);
	}

	private void LoadDefaultNvmHandler(object sender, EventArgs e)
	{
		fmhciMainWorkerThread.WriteNvm(fmhciConfigSettings.DefaultFMHCINVMFile);
	}

	private void LoadNvmHandler(object sender, EventArgs e)
	{
		OpenFileDialog openFileDialog = new OpenFileDialog();
		if (!nvmInitialDirectorySet)
		{
			openFileDialog.InitialDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			nvmInitialDirectorySet = true;
		}
		openFileDialog.Filter = "NVM Files (*.nvm)|*.nvm|All Files (*.*)|*.*";
		if (openFileDialog.ShowDialog() == DialogResult.OK)
		{
			fmhciMainWorkerThread.WriteNvm(openFileDialog.FileName);
		}
	}

	private void LoadDefaultPatchHandler(object sender, EventArgs e)
	{
		fmhciMainWorkerThread.PatchFirmware(fmhciConfigSettings.DefaultFMHCIPatchFile);
	}

	private void LoadPatchHandler(object sender, EventArgs e)
	{
		OpenFileDialog openFileDialog = new OpenFileDialog();
		if (!patchInitialDirectorySet)
		{
			openFileDialog.InitialDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			patchInitialDirectorySet = true;
		}
		openFileDialog.Filter = "Patch Image Files (*.img)|*.img|All Files (*.*)|*.*";
		if (openFileDialog.ShowDialog() == DialogResult.OK)
		{
			fmhciMainWorkerThread.PatchFirmware(openFileDialog.FileName);
		}
	}

	private void LoadDefaultSpurTableHandler(object sender, EventArgs e)
	{
		fmhciMainWorkerThread.LoadSpurTable(fmhciConfigSettings.DefaultFMHCISpurTableFile);
	}

	private void LoadSpurTableHandler(object sender, EventArgs e)
	{
		OpenFileDialog openFileDialog = new OpenFileDialog();
		if (!spurTableInitialDirectorySet)
		{
			openFileDialog.InitialDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			spurTableInitialDirectorySet = true;
		}
		openFileDialog.Filter = "Spur Table Files (*.txt)|*.txt|All Files (*.*)|*.*";
		if (openFileDialog.ShowDialog() == DialogResult.OK)
		{
			fmhciMainWorkerThread.LoadSpurTable(openFileDialog.FileName);
		}
	}

	public void NotifyObserver(ConnectionStateChangeInfo connectionStateChangeInfo)
	{
		if (invokeControl == null)
		{
			UpdateControlEnablesFromConnectionStateChangeInfo(connectionStateChangeInfo);
			return;
		}
		invokeControl.BeginInvoke((MethodInvoker)delegate
		{
			UpdateControlEnablesFromConnectionStateChangeInfo(connectionStateChangeInfo);
		});
	}

	private void UpdateControlEnablesFromConnectionStateChangeInfo(ConnectionStateChangeInfo connectionStateChangeInfo)
	{
		if (connectionStateChangeInfo.openStateChanged)
		{
			if (connectionStateChangeInfo.openState)
			{
				SetControlEnables(ControlEnableMode.CONNECTION_OPENED);
			}
			else
			{
				SetControlEnables(ControlEnableMode.CONNECTION_CLOSED);
			}
		}
	}

	protected virtual void SetControlEnables(ControlEnableMode controlEnableMode)
	{
		switch (controlEnableMode)
		{
		case ControlEnableMode.DEFAULT:
			SetControlEnables(ControlEnableMode.CONNECTION_CLOSED);
			break;
		case ControlEnableMode.CONNECTION_OPENED:
			dropDownMenu.DropDownItems["Open Connection"].Enabled = false;
			toolStripButtonOpenConnection.Enabled = false;
			dropDownMenu.DropDownItems["Close Connection"].Enabled = true;
			toolStripButtonCloseConnection.Enabled = true;
			dropDownMenu.DropDownItems["Load Default NVM File"].Enabled = true;
			dropDownMenu.DropDownItems["Load NVM File"].Enabled = true;
			toolStripButtonLoadDefaultNvm.Enabled = true;
			toolStripButtonLoadNvm.Enabled = true;
			dropDownMenu.DropDownItems["Load Default Patch File"].Enabled = true;
			dropDownMenu.DropDownItems["Load Patch File"].Enabled = true;
			toolStripButtonLoadDefaultPatch.Enabled = true;
			toolStripButtonLoadPatch.Enabled = true;
			dropDownMenu.DropDownItems["Load Default Spur Table File"].Enabled = true;
			dropDownMenu.DropDownItems["Load Spur Table File"].Enabled = true;
			toolStripButtonLoadDefaultSpurTable.Enabled = true;
			toolStripButtonLoadSpurTable.Enabled = true;
			break;
		case ControlEnableMode.CONNECTION_CLOSED:
			dropDownMenu.DropDownItems["Close Connection"].Enabled = false;
			toolStripButtonCloseConnection.Enabled = false;
			dropDownMenu.DropDownItems["Open Connection"].Enabled = true;
			toolStripButtonOpenConnection.Enabled = true;
			dropDownMenu.DropDownItems["Load Default NVM File"].Enabled = false;
			dropDownMenu.DropDownItems["Load NVM File"].Enabled = false;
			toolStripButtonLoadDefaultNvm.Enabled = false;
			toolStripButtonLoadNvm.Enabled = false;
			dropDownMenu.DropDownItems["Load Default Patch File"].Enabled = false;
			dropDownMenu.DropDownItems["Load Patch File"].Enabled = false;
			toolStripButtonLoadDefaultPatch.Enabled = false;
			toolStripButtonLoadPatch.Enabled = false;
			dropDownMenu.DropDownItems["Load Default Spur Table File"].Enabled = false;
			dropDownMenu.DropDownItems["Load Spur Table File"].Enabled = false;
			toolStripButtonLoadDefaultSpurTable.Enabled = false;
			toolStripButtonLoadSpurTable.Enabled = false;
			break;
		default:
			throw new Exception("Unhandled control enable mode: " + controlEnableMode);
		}
	}

	public override void UpdateTitleBar()
	{
		GooierBase.SetWindowText((IntPtr)mainWindowHandle, "QCRPG-FMHCI");
	}
}
