using iBemsDataService.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace iBemsDataService.Controllers.Bems.Common
{
    // TIME_INTERVAL
    public enum TimeInterval
    {
        QuarterMin = 1,
        Hour,
        Day,
        Month,
        Year
    };


    public class PointHistoryValueManager
    {
        iBemsEntities db = null;
        public PointHistoryValueManager(iBemsEntities db)
        {
            this.db = db;
        }

        public CalculationValue[] GetPointValues(int siteId,
            int facilityCode, int propertyId, TimeInterval timeIntervalType,
            DateTime startDate, DateTime endDate)
        {
            switch (timeIntervalType)
            {
                case TimeInterval.QuarterMin:
                    return GetMonitoringPointHistory(
                        db.BemsMonitoringPointHistory15min,
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                case TimeInterval.Hour:
                    return GetMonitoringPointHistory(
                        db.BemsMonitoringPointHistoryHourly,
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                case TimeInterval.Day:
                    return GetMonitoringPointHistory(
                        db.BemsMonitoringPointHistoryDaily,
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                case TimeInterval.Month:
                    return GetMonitoringPointHistoryMonthly(
                        db.BemsMonitoringPointHistoryDaily,
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                case TimeInterval.Year:
                    return GetMonitoringPointHistoryYearly(
                        db.BemsMonitoringPointHistoryDaily,
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                default:
                    throw new Exception("IntervalType Value Error!");

            }
        }

        //예측 데이터 2020.05.**************** kgpark
        public CalculationValue[] GetPointForecastingDayAheadValues(int siteId,
            int facilityCode, int propertyId, TimeInterval timeIntervalType,
            DateTime startDate, DateTime endDate)
        {
            switch (timeIntervalType)
            {
                case TimeInterval.Hour:
                    return GetMonitoringPointHistoryForecastingDayAhead(
                        db.BemsMonitoringPointForecastingDayAhead,
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                default:
                    throw new Exception("IntervalType Value Error!");

            }
        }
        public CalculationValue[] GetMonitoringPointHistoryForecastingDayAhead(
            DbSet<BemsMonitoringPointForecastingDayAhead> dbSet,
            int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate)
        {
            var query = dbSet.Where(x =>
                    x.SiteId == siteId &&
                    x.FacilityCode == facilityCode &&
                    x.PropertyId == propertyId &&
                    startDate <= x.TargetDateTime && x.TargetDateTime <= endDate);

            if (query.Any() == false)
            {
                return null;
            }

            return query.Select(x => new CalculationValue
            {
                DateTime = x.TargetDateTime,
                Value = x.ForecastedValue
            }).ToArray();
        }

        public CalculationValue[] GetPointForecastingHourAheadValues(int siteId,
            int facilityCode, int propertyId, TimeInterval timeIntervalType,
            DateTime startDate, DateTime endDate)
        {
            switch (timeIntervalType)
            {
                case TimeInterval.Hour:
                    return GetMonitoringPointHistoryForecastingHourAhead(
                        db.BemsMonitoringPointForecastingHourAhead,
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                default:
                    throw new Exception("IntervalType Value Error!");

            }
        }
        public CalculationValue[] GetMonitoringPointHistoryForecastingHourAhead(
            DbSet<BemsMonitoringPointForecastingHourAhead> dbSet,
            int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate)
        {
            var query = dbSet.Where(x =>
                    x.SiteId == siteId &&
                    x.FacilityCode == facilityCode &&
                    x.PropertyId == propertyId &&
                    startDate <= x.TargetDateTime && x.TargetDateTime <= endDate);

            if (query.Any() == false)
            {
                return null;
            }

            return query.Select(x => new CalculationValue
            {
                DateTime = x.TargetDateTime,
                Value = x.ForecastedValue
            }).ToArray();
        }
        //예측 데이터 2020.05.**************** kgpark

        //**************** 2020.08. 축열조 시뮬레이터 관련 데이터 가져오기****************** kgpark
        public CalculationValue[] GetPointIceThermalStorageSimulationValues(int siteId,
            int facilityCode, int propertyId, int simulationCase, TimeInterval timeIntervalType,
            DateTime startDate, DateTime endDate)
        {
            switch (timeIntervalType)
            {
                case TimeInterval.QuarterMin:
                    return GetIceThermalStorageSimulation(
                        db.BemsIceThermalStorageSimulation,
                        siteId,
                        facilityCode,
                        propertyId,
                        simulationCase,
                        startDate,
                        endDate);

                default:
                    throw new Exception("IntervalType Value Error!");

            }
        }
        public CalculationValue[] GetIceThermalStorageSimulation(
            DbSet<BemsIceThermalStorageSimulation> dbSet,
            int siteId, int facilityCode, int propertyId, int simulationCase, DateTime startDate, DateTime endDate)
        {
            var query = dbSet.Where(x =>
                    x.SiteId == siteId &&
                    x.FacilityCode == facilityCode &&
                    x.PropertyId == propertyId &&
                    x.SimulationCase == simulationCase &&
                    startDate <= x.TargetDateTime && x.TargetDateTime <= endDate);

            if (query.Any() == false)
            {
                return null;
            }

            return query.Select(x => new CalculationValue
            {
                DateTime = x.TargetDateTime,
                Value = (float)x.SimulationValue
            }).ToArray();
        }
        //**************** 2020.08. 축열조 시뮬레이터 관련 데이터 가져오기****************** kgpark

        public CalculationValue[] GetMonitoringPointHistory(
            DbSet<BemsMonitoringPointHistory15min> dbSet,
            int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate)
        {
            var query = dbSet.Where(x =>
                    x.SiteId == siteId &&
                    x.FacilityCode == facilityCode &&
                    x.PropertyId == propertyId &&
                    startDate <= x.CreatedDateTime && x.CreatedDateTime <= endDate);

            if (query.Any() == false)
            {
                return null;
            }

            return query.Select(x => new CalculationValue
            {
                DateTime = x.CreatedDateTime,
                Value = x.CurrentValue
            }).ToArray();
        }


        public CalculationValue[] GetMonitoringPointHistory(
            DbSet<BemsMonitoringPointHistoryHourly> dbSet,
            int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate)
        {
            var query = dbSet.Where(x =>
                    x.SiteId == siteId &&
                    x.FacilityCode == facilityCode &&
                    x.PropertyId == propertyId &&
                    startDate <= x.CreatedDateTime && x.CreatedDateTime <= endDate);

            if (query.Any() == false)
            {
                return null;
            }

            return query.Select(x => new CalculationValue
            {
                DateTime = x.CreatedDateTime,
                Value = x.CurrentValue

            }).ToArray();
        }

        public CalculationValue[] GetMonitoringPointHistory(
            DbSet<BemsMonitoringPointHistoryDaily> dbSet,
            int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate)
        {
            var query = dbSet.Where(x =>
                    x.SiteId == siteId &&
                    x.FacilityCode == facilityCode &&
                    x.PropertyId == propertyId &&
                    startDate <= x.CreatedDateTime && x.CreatedDateTime <= endDate);

            if (query.Any() == false)
            {
                return null;
            }

            return query.Select(x => new CalculationValue
            {
                DateTime = x.CreatedDateTime,
                //Value = x.CurrentValue hcLee 20150428
                Value = x.DailyValue
            }).ToArray();
        }

        public CalculationValue[] GetMonitoringPointHistoryMonthly(
            DbSet<BemsMonitoringPointHistoryDaily> dbSet,
            int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate)
        {
            var groupQuery = from data in dbSet
                             where data.SiteId == siteId &&
                                     data.FacilityCode == facilityCode &&
                                     data.PropertyId == propertyId &&
                                     startDate <= data.CreatedDateTime && data.CreatedDateTime <= endDate
                             group data by new { Year = data.CreatedDateTime.Year, Month = data.CreatedDateTime.Month } into g
                             select g;
            //select new CalculationValue
            //{ 
            //   DateTime = new DateTime( g.Key.Year , g.Key.Month , 1 ) ,
            //   Value = g.Sum( x => x.CurrentValue )
            //};

            if (groupQuery == null || groupQuery.Any() == false)
            {
                return null;
            }

            CalculationValue[] values = new CalculationValue[groupQuery.Count()];
            var i = 0;
            foreach (var g in groupQuery)
            {
                double dValue = 0;
                if (CheckPointValueType(siteId, facilityCode, propertyId) == 0) dValue = g.Sum(x => x.DailyValue);
                else if (CheckPointValueType(siteId, facilityCode, propertyId) == 1) dValue = g.Average(x => x.DailyValue);
                else if (CheckPointValueType(siteId, facilityCode, propertyId) == 2)
                {
                    dValue = g.Sum(x => x.DailyValue);
                    dValue = (dValue > 0) ? 1 : 0;
                }
                values[i] = new CalculationValue
                {
                    DateTime = new DateTime(g.Key.Year, g.Key.Month, 1),
                    //Value = g.Sum(x => x.CurrentValue)
                    Value = dValue
                };
                i++;
            }

            return values;
        }

        public int CheckPointValueType(int siteId, int facilityCode, int propertyId)
        {
            // return 0 -> 누적, 1 -> 평균,  2 -> On,Off
            var Query = from data in db.BemsMonitoringPoint
                             where data.SiteId == siteId &&
                                     data.FacilityCode == facilityCode &&
                                     data.PropertyId == propertyId select data;

            if (Query.FirstOrDefault().ValueType == 2) return 2;

            if (Query.FirstOrDefault().ValueType == 0 && Query.FirstOrDefault().FuelTypeId > 0) return 0;
            if (Query.FirstOrDefault().ValueType == 0 && Query.FirstOrDefault().FuelTypeId == 0 ) return 1;
            return 0;
        }


        public CalculationValue[] GetMonitoringPointHistoryYearly(
            DbSet<BemsMonitoringPointHistoryDaily> dbSet,
            int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate)
        {
            var groupQuery = from data in dbSet
                             where data.SiteId == siteId &&
                                     data.FacilityCode == facilityCode &&
                                     data.PropertyId == propertyId &&
                                     startDate <= data.CreatedDateTime && data.CreatedDateTime <= endDate
                             group data by new { Year = data.CreatedDateTime.Year } into g
                             select g;
            //select new CalculationValue
            //{
            //    DateTime = new DateTime( g.Key..Year , 1 , 1 ) ,
            //    Value = g.Sum( x => x.CurrentValue )
            //};

            if (groupQuery.Any() == false)
            {
                return null;
            }

            CalculationValue[] values = new CalculationValue[groupQuery.Count()];
            var i = 0;
            foreach (var g in groupQuery)
            {
                values[i] = new CalculationValue
                {
                    DateTime = new DateTime(g.Key.Year, 1, 1),
                    //Value = g.Sum(x => x.CurrentValue)
                    Value = g.Sum(x => x.DailyValue)
                };
                i++;
            }

            return values;
        }
    }

}