using PlantBox.Client.Models;
using PlantBox.Shared.Communication;
using PlantBox.Shared.Communication.Commands;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PlantBox.Client.ViewModels
{
    public class PlantViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public PlantViewModel(PlantInfo plant)
        {
            PlantInfo = plant;

            LoadValues();
        }

        private Historic _historic;
        public Historic Historic
        {
            get => _historic;
            set
            {
                if (value != _historic)
                {
                    _historic = value;
                    OnPropertyChanged();
                }
            }
        }

        private PlantInfo _plantInfo;
        public PlantInfo PlantInfo
        {
            get => _plantInfo;
            set
            {
                if (value != _plantInfo)
                {
                    _plantInfo = value;
                    OnPropertyChanged();
                }
            }
        }

        private CaptorValue _humidityCaptor;
        public CaptorValue HumidityCaptor
        {
            get => _humidityCaptor;
            set
            {
                if (value != _humidityCaptor)
                {
                    _humidityCaptor = value;
                    OnPropertyChanged();
                }
            }
        }

        private CaptorValue _luminosityCaptor;
        public CaptorValue LuminosityCaptor
        {
            get => _luminosityCaptor;
            set
            {
                if (value != _luminosityCaptor)
                {
                    _luminosityCaptor = value;
                    OnPropertyChanged();
                }
            }
        }

        private CaptorValue _temperatureCaptor;
        public CaptorValue TemperatureCaptor
        {
            get => _temperatureCaptor;
            set
            {
                if (value != _temperatureCaptor)
                {
                    _temperatureCaptor = value;
                    OnPropertyChanged();
                }
            }
        }

        private double _tankValue;
        public double TankValue
        {
            get => _tankValue;
            set
            {
                if (value != _tankValue)
                {
                    _tankValue = value;
                    OnPropertyChanged();
                }
            }
        }

        private Duration _historicDuration;
        public Duration HistoricDuration
        {
            get => _historicDuration;
            set
            {
                if (value != _historicDuration)
                {
                    _historicDuration = value;
                    OnPropertyChanged();
                }
            }
        }

        private void LoadValues()
        {
            CaptorValue humidityCaptor;
            CaptorValue luminosityCaptor;
            CaptorValue temperatureCaptor;
            double tankValue;
            HistoricResponse minutelyHistoric;
            HistoricResponse hourlyHistoric;
            HistoricResponse dailyHistoric;
            HistoricResponse monthlyHistoric;

            using (var client = new TcpClient(App.Settings.BrokerIP, Connection.TCP_CLIENT_PORT))
            using (var stream = new CommandStream(client.GetStream()))
            {
                // Captors info
                stream.Send(new CaptorsRequest().ToCommandPacket(PlantInfo.ID));
                (_, var captorsReponse) = stream.Receive<CaptorsResponse>();

                humidityCaptor = new CaptorValue(PlantInfo.HumidityMin, PlantInfo.HumidityMax, captorsReponse.Humidity);
                luminosityCaptor = new CaptorValue(PlantInfo.LuminosityMin, PlantInfo.LuminosityMax, captorsReponse.Luminosity);
                temperatureCaptor = new CaptorValue(PlantInfo.TemperatureMin, PlantInfo.TemperatureMax, captorsReponse.Temperature);
                tankValue = captorsReponse.Tank;

                // Historic
                stream.Send(new HistoricRequest(HistoricInterval.Minutely, 12).ToCommandPacket(PlantInfo.ID));
                (_, minutelyHistoric) = stream.Receive<HistoricResponse>();

                stream.Send(new HistoricRequest(HistoricInterval.Hourly, 48).ToCommandPacket(PlantInfo.ID));
                (_, hourlyHistoric) = stream.Receive<HistoricResponse>();

                stream.Send(new HistoricRequest(HistoricInterval.Daily, 186).ToCommandPacket(PlantInfo.ID));
                (_, dailyHistoric) = stream.Receive<HistoricResponse>();

                stream.Send(new HistoricRequest(HistoricInterval.Monthly, 36).ToCommandPacket(PlantInfo.ID));
                (_, monthlyHistoric) = stream.Receive<HistoricResponse>();
            }

            HumidityCaptor = humidityCaptor;
            LuminosityCaptor = luminosityCaptor;
            TemperatureCaptor = temperatureCaptor;
            TankValue = tankValue;

            var historic = new Historic
            (
                new HistoricEntries(minutelyHistoric, TimeSpan.FromMinutes(5)),
                new HistoricEntries(hourlyHistoric, TimeSpan.FromHours(1)),
                new HistoricEntries(dailyHistoric, TimeSpan.FromDays(1)),
                new HistoricEntries(monthlyHistoric, TimeSpan.FromDays(31))
            );
            Historic = historic;
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
