using CareFusion.Mosaic.Interfaces.Messages.Input;
using System.Collections.Generic;
using System.Linq;

namespace StorageSystemSimulator.Helper
{
    public class InputProcessTracker
    {
        class InputProcess
        {
            private readonly int _inputProcessesID;
            private readonly string _infeedInputId;
            private readonly List<string> _inputRequestIdList = new List<string>();
            private StockInputResponse _inputResponse = null;

            public InputProcess(int inputProcessesID, string infeedInputId)
            {
                _inputProcessesID = inputProcessesID;
                _infeedInputId = infeedInputId;
            }

            public void AddInputRequestId(string inputRequestId)
                => _inputRequestIdList.Add((inputRequestId));

            internal void TrackInputResponse(StockInputResponse inputResponse)
                => _inputResponse = inputResponse;

            public bool IsInputProcessesID(int inputProcessesID)
                => _inputProcessesID == inputProcessesID;

            public bool ContainsInputRequestId(string inputRequestId)
                => _inputRequestIdList.Contains(inputRequestId);

            internal bool ContainsInfeedInputId(string infeedInputId)
                => _infeedInputId == infeedInputId;

            internal StockInputResponse GetInputResponse()
                => _inputResponse;
        }

        private readonly List<InputProcess> inputProcesses = new List<InputProcess>();
        private int _nextInputProcessesID = 0;

        public int AddInputProcess(string infeedInputId)
        {
            inputProcesses.Add(new InputProcess(++_nextInputProcessesID, infeedInputId));
            return _nextInputProcessesID;
        }

        public void AddRequestToInputProcess(int inputProcessesID, string inputRequestId)
            => inputProcesses.Find(ip => ip.IsInputProcessesID(inputProcessesID)).AddInputRequestId(inputRequestId);

        internal void TrackInputResponse(StockInputResponse inputResponse)
            => inputProcesses
                .LastOrDefault(x => x.ContainsInputRequestId(inputResponse.ID))
                ?.TrackInputResponse(inputResponse);

        public void RemoveInputProcess(string inputRequestId)
            => inputProcesses.RemoveAll(x => x.ContainsInputRequestId(inputRequestId));

        public bool IsInputProcessHandled(string inputRequestId)
            => !inputProcesses.Any(x => x.ContainsInputRequestId(inputRequestId));

        internal StockInputResponse GetInputResponseByInfeedInputId(string infeedInputId)
            => inputProcesses
                .LastOrDefault(x => x.ContainsInfeedInputId(infeedInputId))
                ?.GetInputResponse();
    }
}