using Client.DataStructures;
using Client.ISServiceRef;
using Client.View;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using LiveCharts;
using LiveCharts.Wpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media;
using WpfAsyncPack.Command;

namespace Client.ViewModel
{
    public class AttendanceStatisticsViewModel : ViewModelBase
    {

        public MonthlyAttendanceData MonthlyAttendanceData { get; set; }

        public double TotalHours { get; set; }
        public double LunchBreakHours { get; set; }
        public double VacationHours { get; set; }
        public double MedicalLeaveHours { get; set; }
        public double WorkHours { get; set; }

        public SeriesCollection HourDistributionSeries { get; set; }

        public AttendanceStatisticsViewModel(MonthlyAttendanceData monthlyAttendanceData, bool initCharts = true)
        {
            MonthlyAttendanceData = monthlyAttendanceData;

            CalculateVacationTime();
            CalculateLunchBreaks();
            CalculateMedicalLeaveHours();
            CalculateTotalHours();

            if (initCharts == true)
                InitHourDistributionChart();
        }


        private void CalculateVacationTime()
        {
            double vacationHours = 0;
            var vacationBeginnings = MonthlyAttendanceData.AttendanceRecords.Where(x => x.AttendanceEventType.Name == Properties.Resources.VacationBegin).OrderBy(x => x.TimeStamp);
            var vacationEndings = MonthlyAttendanceData.AttendanceRecords.Where(x => x.AttendanceEventType.Name == Properties.Resources.VacationEnd).OrderBy(x => x.TimeStamp);

            foreach (var vacationBeginning in vacationBeginnings)
            {
                var vacationEnding = vacationEndings.FirstOrDefault(x => x.TimeStamp > vacationBeginning.TimeStamp);
                if (vacationEnding == null) continue;

                var daysOnVacation = vacationEnding.TimeStamp.Day - vacationBeginning.TimeStamp.Day + 1;

                if (vacationEnding.TimeStamp.Day == vacationBeginning.TimeStamp.Day)
                {
                    var hours = (vacationEnding.TimeStamp - vacationBeginning.TimeStamp).TotalHours;
                    vacationHours += hours < 8 ? hours : 8;
                }
                else
                {
                    for(int i = 0; i < daysOnVacation; i++)
                    {
                        var timeStamp = vacationBeginning.TimeStamp.AddDays(i);
                        if (timeStamp.DayOfWeek == DayOfWeek.Sunday || timeStamp.DayOfWeek == DayOfWeek.Saturday)
                            continue;

                        vacationHours += 8;
                    }
                }

            }

            VacationHours = Math.Round(vacationHours, 2);
        }

        private void CalculateTotalHours()
        {
            double totalHours = 0;
            var arrivals = MonthlyAttendanceData.AttendanceRecords.Where(x => x.AttendanceEventType.Name == Properties.Resources.Arrival);
            var departures = MonthlyAttendanceData.AttendanceRecords.Where(x => x.AttendanceEventType.Name == Properties.Resources.Departure);

            foreach(var arrival in arrivals)
            {
                var departure = departures.FirstOrDefault(x => x.TimeStamp.DayOfYear == arrival.TimeStamp.DayOfYear);

                if (departure == null) continue;

                totalHours += (departure.TimeStamp - arrival.TimeStamp).TotalHours;

            }

            TotalHours = Math.Round(totalHours, 2) + VacationHours;
            WorkHours = TotalHours - MedicalLeaveHours - LunchBreakHours - VacationHours;
        }

        private void CalculateLunchBreaks()
        {
            double lunchHours = 0;
            var lunchDepartures = MonthlyAttendanceData.AttendanceRecords.Where(x => x.AttendanceEventType.Name == Properties.Resources.LunchBreakDeparture);
            var lunchArrivals = MonthlyAttendanceData.AttendanceRecords.Where(x => x.AttendanceEventType.Name == Properties.Resources.LunchBreakArrival);

            foreach (var lunchDeparture in lunchDepartures)
            {
                var lunchArrival = lunchArrivals.FirstOrDefault(x => x.TimeStamp.DayOfYear == lunchDeparture.TimeStamp.DayOfYear);

                if (lunchArrival == null) continue;

                lunchHours += (lunchArrival.TimeStamp - lunchDeparture.TimeStamp).TotalHours;
            }

            LunchBreakHours = Math.Round(lunchHours, 2);
        }

        private void CalculateMedicalLeaveHours()
        {
            double medicalLeaveHours = 0;
            var medicalDepartures = MonthlyAttendanceData.AttendanceRecords.Where(x => x.AttendanceEventType.Name == Properties.Resources.MedicalDeparture);
            var medicalArrivals = MonthlyAttendanceData.AttendanceRecords.Where(x => x.AttendanceEventType.Name == Properties.Resources.MedicalArrival);

            foreach (var medicalDeparture in medicalDepartures)
            {
                var medicalArrival = medicalArrivals.FirstOrDefault(x => x.TimeStamp.DayOfYear == medicalDeparture.TimeStamp.DayOfYear);

                if (medicalArrival == null) continue;

                medicalLeaveHours += (medicalArrival.TimeStamp - medicalDeparture.TimeStamp).TotalHours;
            }

            MedicalLeaveHours = Math.Round(medicalLeaveHours, 2);
        }


        private void InitHourDistributionChart()
        {
            HourDistributionSeries = new SeriesCollection()
            {
                new PieSeries()
                {
                    Title = Properties.Resources.Work,
                    Values = new ChartValues<double>(new double[] {WorkHours }),
                    DataLabels = true,
                    LabelPoint = _labelFunc,
                    Stroke = new SolidColorBrush(Color.FromArgb(255, 214, 223, 225))
                },
                new PieSeries()
                {
                    Title = Properties.Resources.LunchBreak,
                    Values = new ChartValues<double>(new double[] {LunchBreakHours }),
                    DataLabels = true,
                    LabelPoint = _labelFunc,
                    Stroke = new SolidColorBrush(Color.FromArgb(255, 214, 223, 225))
                },
                new PieSeries()
                {
                    Title = Properties.Resources.VacationHours,
                    Values = new ChartValues<double>(new double[] {VacationHours }),
                    DataLabels = true,
                    LabelPoint = _labelFunc,
                    Stroke = new SolidColorBrush(Color.FromArgb(255, 214, 223, 225))
                },
                new PieSeries()
                {
                    Title = Properties.Resources.MedicalHours,
                    Values = new ChartValues<double>(new double[] {MedicalLeaveHours }),
                    DataLabels = true,
                    LabelPoint = _labelFunc,
                    Stroke = new SolidColorBrush(Color.FromArgb(255, 214, 223, 225))
                },
            };
        }


        private Func<ChartPoint, string> _labelFunc = (chartPoint) => { return string.Format("{0}", chartPoint.Y); };

    }
}
