using Gebhardt.Shared;
using System.Collections.Generic;
using System.Linq;

namespace Gebhardt.StoreWare.Wcs.Common
{

	#region Send Methoden
	/// <summary>
	/// Klasse dient zum Senden von Telegrammen an die SPS
	/// </summary>
	public static partial class ConveyorTelegrams
	{

		private static List<string> destinationsOldSystem = new List<string>() {
			Constants.MfcAllDestinationsOldSystem.ETXBU,
			Constants.MfcAllDestinationsOldSystem.ETXBU_M,
			Constants.MfcAllDestinationsOldSystem.ETXBU_S,
			Constants.MfcAllDestinationsOldSystem.IPT01,
			Constants.MfcAllDestinationsOldSystem.IPT02,
			Constants.MfcAllDestinationsOldSystem.IPT03,
			Constants.MfcAllDestinationsOldSystem.IPT01,
			Constants.MfcAllDestinationsOldSystem.REP01,
			Constants.MfcAllDestinationsOldSystem.REP02,
			Constants.MfcAllDestinationsOldSystem.REP03,

			Constants.MfcAllDestinationsOldSystem.ETM01,
			Constants.MfcAllDestinationsOldSystem.ETM02,
			Constants.MfcAllDestinationsOldSystem.ETM03,
			Constants.MfcAllDestinationsOldSystem.ETS01,
			Constants.MfcAllDestinationsOldSystem.ETS02,
			Constants.MfcAllDestinationsOldSystem.ETS03,
			Constants.MfcAllDestinationsOldSystem.QCS01,
			Constants.MfcAllDestinationsOldSystem.QCS02,
			Constants.MfcAllDestinationsOldSystem.ERR01,
			Constants.MfcAllDestinationsOldSystem.TOPUP,
			//Constants.MfcAllDestinationsOldSystem.ERS01,
			Constants.MfcAllDestinationsOldSystem.LOOP3,
			Constants.MfcAllDestinationsOldSystem.C0101,
			Constants.MfcAllDestinationsOldSystem.C0201,
			Constants.MfcAllDestinationsOldSystem.S0300,
			Constants.MfcAllDestinationsOldSystem.S0301,
			Constants.MfcAllDestinationsOldSystem.S0302,
			Constants.MfcAllDestinationsOldSystem.S0303,
			Constants.MfcAllDestinationsOldSystem.S0304,
			Constants.MfcAllDestinationsOldSystem.S0305,
			Constants.MfcAllDestinationsOldSystem.S0400,
			Constants.MfcAllDestinationsOldSystem.S0401,
			Constants.MfcAllDestinationsOldSystem.S0402,
			Constants.MfcAllDestinationsOldSystem.S0403,
			Constants.MfcAllDestinationsOldSystem.S0404,
			Constants.MfcAllDestinationsOldSystem.S0405,
			//Scanner Replenishment
			Constants.MfcScannerOldSystem.SC101,
			Constants.MfcScannerOldSystem.SC102,
			Constants.MfcScannerOldSystem.SC103,
			Constants.MfcScannerOldSystem.SC104,
			Constants.MfcScannerOldSystem.SC105,
			Constants.MfcScannerOldSystem.SC106,
			Constants.MfcScannerOldSystem.SC107,
			//Scanner Loop+Cranes
			Constants.MfcScannerOldSystem.SC201,
			Constants.MfcScannerOldSystem.SC202,
			Constants.MfcScannerOldSystem.SC203,
			Constants.MfcScannerOldSystem.SC204,
			Constants.MfcScannerOldSystem.SC205,
			Constants.MfcScannerOldSystem.SC206,
			Constants.MfcScannerOldSystem.SC207,
			Constants.MfcScannerOldSystem.SC208,
			Constants.MfcScannerOldSystem.SC209,
			Constants.MfcScannerOldSystem.SC210,
			Constants.MfcScannerOldSystem.SC211,

			Constants.MfcScannerOldSystem.SC301,
			Constants.MfcScannerOldSystem.SC302,
			Constants.MfcScannerOldSystem.SC303,
			Constants.MfcScannerOldSystem.SC304,
			Constants.MfcScannerOldSystem.SC305,
			Constants.MfcScannerOldSystem.SC306,
			Constants.MfcScannerOldSystem.SC307,
			Constants.MfcScannerOldSystem.SC308,
			Constants.MfcScannerOldSystem.SC309,
			Constants.MfcScannerOldSystem.SC310,

			//MLS Aisles
			Constants.MfcScannerOldSystem.SC401,
			Constants.MfcScannerOldSystem.SC402,
			Constants.MfcScannerOldSystem.SC403,
			Constants.MfcScannerOldSystem.SC404,
			Constants.MfcScannerOldSystem.SC405,
			Constants.MfcScannerOldSystem.SC406,
			Constants.MfcScannerOldSystem.SC407,
			Constants.MfcScannerOldSystem.SC408,
			Constants.MfcScannerOldSystem.SC409,
			Constants.MfcScannerOldSystem.SC410,
			Constants.MfcScannerOldSystem.SC411,
			Constants.MfcScannerOldSystem.SC412,

			//Constants.MfcScannerOldSystem.SC501,
			//Constants.MfcScannerOldSystem.SC502,
			//Constants.MfcScannerOldSystem.SC503,
			//Constants.MfcScannerOldSystem.SC504,
			//Constants.MfcScannerOldSystem.SC505,

			//Constants.MfcScannerOldSystem.SC601,
			//Constants.MfcScannerOldSystem.SC602,
			//Constants.MfcScannerOldSystem.SC603,
			//Constants.MfcScannerOldSystem.SC604,
			//Constants.MfcScannerOldSystem.SC605
		};

		#region SendTord Methoden MFRtoSPS
		/// <summary>
		/// Transportorder to device PLCs
		/// <para>Richtung : MFRtoSPS</para>
		/// <para>pFillContent  true</para>
		/// <para>Wenn pFillContent True, wird Telegram mit dem Zeichen '0' linksbündig aufgefüllt.</para>
		/// </summary>
		/// <param name = "db">Ef Core Database Context</param>

		/// <param name = "pHU"> (Lenght:8 PadChar:'*' L/R: L)</param>
		/// <param name = "pSrc">Source (Lenght:11 PadChar:'-' L/R: R)</param>
		/// <param name = "pDest">Destination (Lenght:11 PadChar:'-' L/R: R)</param>
		/// <param name = "pType">LE type from DB (Lenght:10 PadChar:'0' L/R: R)</param>
		/// <param name = "pToID">Orders Conveyor ID (Lenght:10 PadChar:'0' L/R: L)</param>
		/// <returns></returns>
		public static bool SendTordEtra(Gebhardt.StoreWare.Wcs.Common.DbAccess.IWcsDbContext db, string pHU, string pSrc, string pDest, string pType, string pToID)
		{
			bool sent = false;
			if (pDest.Contains("EMB") || pSrc.Contains("EMB") || pSrc.Contains(Constants.MfcScanner.SC0505) || pSrc.Contains(Constants.MfcScanner.SC0137) || pSrc.Contains(Constants.MfcScanner.SC0183))
			{
				sent = SendTordWithDefaults(db, p_HU: pHU, p_Src: pSrc, p_Dest: pDest, p_Type: pType, p_ToID: pToID,
				p_DataDestination: ConveyorTelegramsDataDestination.D_PLC05);
			}
			else if (pDest.StartsWith("PIC1"))
			{
				sent = SendTordWithDefaults(db, p_HU: pHU, p_Src: pSrc, p_Dest: pDest, p_Type: pType, p_ToID: pToID,
					p_DataDestination: ConveyorTelegramsDataDestination.D_PLC03);
			}
			else if (pSrc.Contains(Constants.MfcAllDestinations.ERR12) || pSrc.StartsWith("SEQ") || pDest.StartsWith("PIC2"))
			{
				sent = SendTordWithDefaults(db, p_HU: pHU, p_Src: pSrc, p_Dest: pDest, p_Type: pType, p_ToID: pToID,
				p_DataDestination: ConveyorTelegramsDataDestination.D_PLC02);
			}
			// Old telegrams
			// TODO: Fix to send to 01 for real system!
			if (destinationsOldSystem.Contains(pSrc) || destinationsOldSystem.Contains(pDest))
			{
				var leType = db.LeType.Where(t => t.TypePrefix == pHU.Substring(0, 1)).FirstOrDefault();
				int minWeight = 1000;
				int maxWeight = 50000;
				if (leType != null)
				{
					minWeight = leType.TareWeight - 1000;
					maxWeight = leType.MaxWeight;
				}
				string destinationForOldSystem = pDest;
				string[] replenishmentArea = new[]
				{
					Constants.MfcAllDestinationsOldSystem.IPT01,
					Constants.MfcAllDestinationsOldSystem.IPT02,
					Constants.MfcAllDestinationsOldSystem.IPT03,
					Constants.MfcAllDestinationsOldSystem.ETXBU,
					Constants.MfcAllDestinationsOldSystem.ETXBU_M,
					Constants.MfcAllDestinationsOldSystem.ETXBU_S,
					Constants.MfcScannerOldSystem.SC102,
					Constants.MfcScannerOldSystem.SC101,
					Constants.MfcScannerOldSystem.SC103,
					Constants.MfcAllDestinationsOldSystem.TOPUP
				};

				if (!destinationsOldSystem.Contains(pDest))
				{
					destinationForOldSystem = Constants.MfcAllDestinationsOldSystem.QCS01;
				}
				if (replenishmentArea.Contains(pDest) || replenishmentArea.Contains(pSrc))
				{
					sent = Send0001WithDefaults(db, ConveyorTelegramsDataSource.S_31, ConveyorTelegramsDataDestination.D_02, pHU,
					destinationForOldSystem, p_WgtMin: minWeight.ToString(), p_WgtMax: maxWeight.ToString());
				}
				sent = Send0001WithDefaults(db, ConveyorTelegramsDataSource.S_31, ConveyorTelegramsDataDestination.D_01, pHU,
				destinationForOldSystem, p_WgtMin: minWeight.ToString(), p_WgtMax: maxWeight.ToString());

			}
			//Don't send to new system if both source and destination are in old system
			if (!(destinationsOldSystem.Contains(pSrc) && destinationsOldSystem.Contains(pDest)))
			{
				//If only Destination is in old system, we need to tell the new system to drive to LOOP3, only this destination is known 
				if (destinationsOldSystem.Contains(pDest))
				{
					pDest = Constants.MfcAllDestinationsOldSystem.LOOP3;
				}
				sent = SendTordWithDefaults(db, p_HU: pHU, p_Src: pSrc, p_Dest: pDest, p_Type: pType, p_ToID: pToID,
						p_DataDestination: ConveyorTelegramsDataDestination.D_PLC01);
			}

			return sent;
		}

		public static bool SendTordPalletizingEtra(Gebhardt.StoreWare.Wcs.Common.DbAccess.IWcsDbContext db, string pHU, string pSrc, string pToID, List<string> pDestList)
		{
			//PLC needs the order to be ascending according to transport direction
			pDestList = pDestList.OrderBy(d => d.Substring(d.Length - 1, 1)).ToList();
			return SendTordWithDefaults(db, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC02, p_HU: pHU, p_Src: pSrc, p_ToID: pToID, p_DestList: $"[{string.Join(',', pDestList)}]", p_Dest: pDestList[0]);
		}

		public static bool SendTordPalletDispatchLineEtra(Gebhardt.StoreWare.Wcs.Common.DbAccess.IWcsDbContext db, string pHU, string pSrc, string pToID, string pDest, bool pWrap, bool pPrint)
		{
			return SendTordWithDefaults(db, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC07, p_HU: pHU, p_Src: pSrc, p_Dest: pDest, p_ToID: pToID, p_Wrap: pWrap ? "1" : "0", p_Print: pPrint ? "1" : "0");
		}

		#endregion SendTord Methoden  MFRtoSPS

		#region SendDeparture Methoden MFRtoSPS
		/// <summary>
		/// Departs immediately
		/// <para>Richtung : MFRtoSPS</para>
		/// <para>pFillContent  true</para>
		/// <para>Wenn pFillContent True, wird Telegram mit dem Zeichen '0' linksbündig aufgefüllt.</para>
		/// </summary>
		/// <param name = "db">Ef Core Database Context</param>

		/// <param name = "pHU"> (Lenght:8 PadChar:'*' L/R: L)</param>
		/// <param name = "pSrc"> (Lenght:11 PadChar:'-' L/R: R)</param>
		/// <returns></returns>.
		public static bool SendDepartureEtra(Gebhardt.StoreWare.Wcs.Common.DbAccess.IWcsDbContext db, string pHU, string pSrc)
		{
			if (pSrc.StartsWith("PIC1"))
			{
				return SendDepartureWithDefaults(db, p_HU: pHU, p_Src: pSrc, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC03);

			}
			if (pSrc.StartsWith("PIC2") || pSrc.StartsWith(Common.Constants.MfcAllDestinations.ERR12))
			{
				return SendDepartureWithDefaults(db, p_HU: pHU, p_Src: pSrc, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC02);
			}
			if (pSrc.StartsWith(Common.Constants.MfcAllDestinations.ERR11))
			{
				return SendDepartureWithDefaults(db, p_HU: pHU, p_Src: pSrc, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC05);
			}

			if (destinationsOldSystem.Contains(pSrc))
			{
				return Send0006WithDefaults(db, p_HU: pHU, p_Src: pSrc);
			}

			return SendDepartureWithDefaults(db, p_HU: pHU, p_Src: pSrc);
		}

		#endregion SendDepature Methoden  MFRtoSPS

		#region SendTordDelete Methoden MFRtoSPS
		/// <summary>
		/// Delete an order
		/// <para>Richtung : MFRtoSPS</para>
		/// <para>pFillContent  true</para>
		/// <para>Wenn pFillContent True, wird Telegram mit dem Zeichen '0' linksbündig aufgefüllt.</para>
		/// </summary>
		/// <param name = "db">Ef Core Database Context</param>

		/// <param name = "pHU"> (Lenght:12 PadChar:'*' L/R: L)</param>
		/// <param name = "pToID">Orders Conveyor ID (Lenght:10 PadChar:'0' L/R: L)</param>
		/// <returns></returns>
		public static bool SendTordDeleteEtra(Gebhardt.StoreWare.Wcs.Common.DbAccess.IWcsDbContext db, string pHU)
		{
			//Todo: only send Tords to PLCs involved in the transport?
			SendTordDeleteWithDefaults(db, p_HU: pHU, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC01);
			SendTordDeleteWithDefaults(db, p_HU: pHU, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC02);
			SendTordDeleteWithDefaults(db, p_HU: pHU, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC03);
			SendTordDeleteWithDefaults(db, p_HU: pHU, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC05);
			//Old PLC
			Send0002WithDefaults(db, p_HU: pHU, p_DataDestination: ConveyorTelegramsDataDestination.D_01);
			Send0002WithDefaults(db, p_HU: pHU, p_DataDestination: ConveyorTelegramsDataDestination.D_02);
			return SendTordDeleteWithDefaults(db, p_HU: pHU, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC07);

		}
		#endregion SendTordDelete Methoden  MFRtoSPS

		#region SendResetData Methoden MFRtoSPS
		/// <summary>
		///TelegramsContent hat Constant Parameters
		/// Reset data
		/// <para>Richtung : MFRtoSPS</para>
		/// <para>pFillContent true</para>
		/// <para>Wenn pFillContent True, wird Telegram mit dem Zeichen '0' linksbündich ausgefüllt.</para>
		/// </summary>

		/// <param name = "pDataDestination">Ziel</param>

		/// <param name = "p_Info"> (Lenght:50 PadChar:'§' L/R: R)</param>
		/// <returns></returns>
		public static bool SendResetDataEtra(DbAccess.IWcsDbContext db, Enums.ResetDataInfos p_Info)
		{
			SendResetDataWithDefaults(db, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC01, p_Info: p_Info.GetEnumDescription());
			SendResetDataWithDefaults(db, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC02, p_Info: p_Info.GetEnumDescription());
			SendResetDataWithDefaults(db, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC03, p_Info: p_Info.GetEnumDescription());
			SendResetDataWithDefaults(db, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC05, p_Info: p_Info.GetEnumDescription());
			Send0004WithDefaults(db);
			return SendResetDataWithDefaults(db, p_DataDestination: ConveyorTelegramsDataDestination.D_PLC07, p_Info: p_Info.GetEnumDescription());
		}

		#endregion SendResetData Methoden  MFRtoSPS
	}
	#endregion
}