using System;
using System.Collections.Generic;
using System.Linq;
using Wayne.Lib;
using Wayne.Lib.StateEngine;
using Wayne.Lib.StateEngine.Generic;

namespace SinochemInternetPlusApp.States.CarPlateMode
{
    public class WaitForFueling : TimeoutState<FuelingPoint>
    {
        private byte sqNo;
        private bool cardReaderBackToIdle = false;
        private bool nozzleLifted = false;

        protected override void Enter(StateEntry stateEntry, ref Transition transition)
        {
            base.Enter(stateEntry, ref transition);

            cardReaderBackToIdle = false;
            nozzleLifted = false;

            Main.SetICCardReaderToCarPlateIdle(out sqNo);
            DebugLog($"Start to set card reader back to CarPlateIdle, SqNo={sqNo}\n Waiting for Ack");
        }

        protected override void HandleNonTimeoutEvent(StateEngineEvent stateEngineEvent, ref Transition transition)
        {
            if (stateEngineEvent.Type.Equals(EventType.NozzleLifted))
            {
                var nlEvent = stateEngineEvent as GenericEvent<NozzleLiftedEventArgs>;
                if (nlEvent.EventArgs.NozzleId == Main.CurrentNozzleId)
                { 
                    DebugLog("Nozzle correctly lifted");
                    nozzleLifted = true;
                }
                else
                {
                    DebugLog("Nozzle lifted, but the nozzle was wrong: " + nlEvent.EventArgs.NozzleId);
                }

                stateEngineEvent.Handled = true;
            }

            if (stateEngineEvent.Type.Equals(EventType.NozzleReplaced))
            {
                var nrEvent = stateEngineEvent as GenericEvent<NozzleReplacedEventArgs>;
                if(nrEvent.EventArgs.NozzleId != Main.CurrentNozzleId)
                {
                    DebugLog("Nozzle replaced, but the nozzle was wrong: " + nrEvent.EventArgs.NozzleId);
                    stateEngineEvent.Handled = true;
                }
            }

            GenericEvent<CardReaderAckEventArgs> ackEvent = stateEngineEvent as GenericEvent<CardReaderAckEventArgs>;
            if (ackEvent != null && ackEvent.EventArgs != null)
            {
                if (ackEvent.EventArgs.Ack.MessageSeqNumber == sqNo)
                {
                    DebugLog($" Set CardReader to CarPlateIdle ack'ed, SqNo={sqNo}\n");

                    ackEvent.Handled = true;
                    cardReaderBackToIdle = true;
                }
            }

            if (stateEngineEvent.Type.Equals(EventType.TrxOpRequest))
            {
                GenericEvent<TransactionOperationEventArgs> trxOpEvent = stateEngineEvent as GenericEvent<TransactionOperationEventArgs>;
                if (trxOpEvent != null && trxOpEvent.EventArgs != null && Main.ActiveTrx != null)
                {
                    trxOpEvent.Handled = true;

                    if (trxOpEvent.EventArgs.TrxOp.OpType == OpType.Delete)
                    {
                        int trxId = trxOpEvent.EventArgs.TrxOp.TrxId;

                        foreach (var trx in Main.ActiveTrx)
                        {
                            if ((trx.id == trxId) && (Main.AssociatedNozzles.Contains(trx.jihao)))
                            {                                
                                EpsTransaction.RestroeEpsTrxFrom(trx).UpdateTrxStatusToDb(EpsTrxStatus.Removed);
                                Main.CurrentEpsTrx = null;
                                transition = new Transition(this, TransitionType.FuelingRemoved);
                            }
                        }
                    }
                }
            }

            if (nozzleLifted && cardReaderBackToIdle)
            {
                transition = new Transition(this, TransitionType.NozzleLifted);
            }
        }

        protected override void Timeout(ref Transition transition)
        {
            transition = new Transition(this, TransitionType.Timeout);
        }

        protected override int TimeoutInterval =>
            TimeoutValues.GetValueInMilliSec(TimeoutValues.FuelingPoint.Shared_WaitForFueling, 30 * 60);
    }
}