// Copyright © Selmo Technology GmbH. All Rights Reserved

using SelmoStudio.Hmi.Server.SelmoHmi.Model.Dtos;
using SelmoStudio.Hmi.Server.SelmoHmi.Model.ProjectItems;
using SelmoStudio.Hmi.Server.SelmoHmi.Plant.Model;
using SelmoStudio.Hmi.Server.SelmoHmi.Sequence.Model;
using SelmoStudio.Hmi.Server.SelmoHmi.Shared.Service;

namespace SelmoStudio.Hmi.Server.SelmoHmi.ProjectInformation.Service
{
    public class ProjectInformationService : IProjectInformationService
    {
        private IProjectService _projectService;
        private IList<ProjectItemCollectionHwInfo> _hardwareZones;
        private ProjectItemCollectionPlant _currentPlant;
        private ProjectItemCollectionHwInfo _currentHardwareZone;
        private ProjectItemCollectionSequence _currentSequence;
        private ContentInfo _currentContentInfo;
        private readonly Dictionary<string, object> _parameters = new();

        public event Action SequenceUpdated;

        public event Func<Task> SequenceUpdatedAsync;

        public IReadOnlyList<ProjectItemCollectionHwInfo> HardwareZones => _hardwareZones.ToList();
        public IReadOnlyList<HardwareZoneInfoDto> HardwareZoneInfos => _hardwareZones.Select(hwz => hwz.HardwareZoneInfo).ToList();
        public ProjectItemCollectionPlant CurrentPlant => _currentPlant;
        public IReadOnlyList<ProjectItemCollectionSequence> Sequences => CurrentHardwareZone.Sequences;

        public ProjectItemCollectionHwInfo CurrentHardwareZone
        {
            get
            {
                if (_currentHardwareZone == null)
                {
                    _currentHardwareZone = GetCurrentHardwareZone();
                }

                return _currentHardwareZone;
            }
        }

        public ProjectItemCollectionSequence CurrentSequence
        {
            get
            {
                if (_currentSequence == null)
                {
                    _currentSequence = GetCurrentSequence();
                }

                return _currentSequence;
            }
        }

        public ContentInfo CurrentContentInfo => _currentContentInfo;

        public ProjectInformationService(IProjectService projectService)
        {
            _projectService = projectService;
            InitHardwareZones(_projectService);
        }

        public void SelectHardwareZone(HardwareZoneInfoDto hardwareZoneInfo)
        {
            var hardwareZone = _hardwareZones.FirstOrDefault(h => h.HardwareZoneInfo.Id.Equals(hardwareZoneInfo.Id));

            if (hardwareZone != null)
            {
                _currentHardwareZone = hardwareZone;

                var sequenceToSelect = _currentHardwareZone.Sequences.FirstOrDefault();

                if (sequenceToSelect != null)
                {
                    SelectSequence(sequenceToSelect);
                }
            }
        }

        public void SelectSequence(ProjectItemCollectionSequence sequence)
        {
            _currentSequence = sequence;

            SequenceUpdated?.Invoke();

            Task.Run(async () =>
            {
                if (SequenceUpdatedAsync != null)
                {
                    await SequenceUpdatedAsync.Invoke();
                }
            });
        }

        public void SelectContentInfo(ContentInfo contentInfo)
        {
            _currentContentInfo = contentInfo;
        }

        public bool TryGetParameter<T>(string parameterName, out T value)
        {
            if (_parameters.TryGetValue(parameterName, out var storedValue) && storedValue is T typedValue)
            {
                value = typedValue;
                return true;
            }

            value = default;
            return false;
        }

        public void SetParameter<T>(string parameterName, T value)
        {
            if (_parameters.ContainsKey(parameterName))
            {
                _parameters[parameterName] = value;
            }
            else
            {
                _parameters.Add(parameterName, value);
            }
        }

        public void ClearParameters()
        {
            _parameters.Clear();
        }

        private void InitHardwareZones(IProjectService projectService)
        {
            var project = projectService.GetProject();

            if (project == null || project.Plants == null || project.Plants.Count == 0)
            {
                _hardwareZones = new List<ProjectItemCollectionHwInfo>();
            }
            else
            {
                _currentPlant = project.Plants[0];
                _hardwareZones = project.Plants[0].HardwareZones;
            }
        }

        private ProjectItemCollectionHwInfo GetCurrentHardwareZone()
        {
            if (_hardwareZones != null && _hardwareZones.Any())
            {
                return _hardwareZones.First();
            }

            return new ProjectItemCollectionHwInfo();
        }

        private ProjectItemCollectionSequence GetCurrentSequence()
        {
            if (Sequences != null && Sequences.Any())
            {
                return Sequences.First();
            }

            return new ProjectItemCollectionSequence();
        }
    }
}