using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Dapper.ResultData;
using Siger.Middlelayer.Dapper.Utilities.Slice;
using Siger.Middlelayer.Share.Models;
using Siger.Middlelayer.Share.Utilities;

namespace Siger.Middlelayer.Dapper.Utilities.Oee
{
    public class OeeManager
    {
        public static OeeDetailEntity GetOeeByTime(DateTime dtStart, DateTime dtEnd, IEnumerable<CncSliceSate> sliceSates,
            IEnumerable<int> machineIds, IEnumerable<ProductReport> reports, IEnumerable<MachineRestInfo> times)
        {
            double newRun = 0;
            double run = 0;
            double oee1 = 0.0;
            double oee2 = 100.0;
            double oee3 = 100.0;

            if (dtEnd > DateTime.Now)
            {
                dtEnd = DateTime.Now;
            }

            var holdTimes = SliceManager.GetMachineStatusHold(machineIds, dtStart, dtEnd, sliceSates);
            if (holdTimes != null && holdTimes.Any())
            {
                foreach (var shutdownHoldTime in holdTimes)
                {
                    if (shutdownHoldTime.Status == MachineRunningStatus.Running)
                    {
                        run += shutdownHoldTime.TimeSpan;
                    }
                }
            }

            foreach (var machineId in machineIds)
            {
                var ss = RestTimeManager.GetNewRun(machineId, dtStart, dtEnd, times);
                newRun += RestTimeManager.GetNewRun(machineId, dtStart, dtEnd, times);
            }
            if (newRun > 0)
            {
                 oee1 = run / newRun * 100;
            }

            if (reports != null && reports.Any())
            {
                double theoryYield = 0; // 理论产量
                double actualOutput = 0;
                double nokNumber = 0;
                foreach (var productReport in reports)
                {
                    actualOutput += productReport.ActualOutput;
                    nokNumber += productReport.NokNumber;

                    var startTime = UnixTimeHelper.ConvertStringDateTime(productReport.StartTime.ToString());
                    var endTime = UnixTimeHelper.ConvertStringDateTime(productReport.EndTime.ToString());

                    double reportRun = 0;
                    var runHoldTimes = SliceManager.GetMachineStatusHold(machineIds, startTime, endTime, sliceSates);
                    if (runHoldTimes != null)
                    {
                        reportRun = runHoldTimes.First(q => q.Status == MachineRunningStatus.Running).TimeSpan;
                    }

                    if (reportRun <= 0)
                    {
                        reportRun = productReport.EndTime - productReport.StartTime;
                    }

                    theoryYield += productReport.CycleTime == 0 ? 0 : reportRun / productReport.CycleTime;
                }
                oee2 = theoryYield <= 0 ? 0 : (actualOutput + nokNumber) / theoryYield * 100;
                oee3 = (actualOutput + nokNumber) <= 0 ? 0 : actualOutput / (actualOutput + nokNumber) * 100;
            }

            return new OeeDetailEntity(oee1, oee2, oee3) { Run = run, Sum = newRun };
        }

        public static OeeDetailEntity GetOeeByTimeTwo(DateTime dtStart, DateTime dtEnd, IEnumerable<CncSliceSate> sliceSates,
            IEnumerable<int> machineIds, IEnumerable<ProductReport> reports, IEnumerable<MachineRestInfo> times)
        {
            double newRun = 0;
            double run = 0;
            double oee1 = 0.0;
            double oee2 = 100.0;
            double oee3 = 100.0;

            if (dtEnd > DateTime.Now)
            {
                dtEnd = DateTime.Now;
            }
            foreach (var sate in sliceSates)
            {
                var data = new MachineStatusHold
                {
                    machine_status = sate.Status,
                    time_span = (sate.EndTime - sate.StartTime).TotalSeconds,
                    start_time = (int)UnixTimeHelper.ConvertDataTimeLong(sate.StartTime),
                    end_time = (int)UnixTimeHelper.ConvertDataTimeLong(sate.EndTime)
                };
                if (sate.StartTime < dtStart)
                {
                    data.start_time = (int)UnixTimeHelper.ConvertDataTimeLong(dtStart);
                }
                if (sate.EndTime > dtEnd)
                {
                    data.end_time = (int)UnixTimeHelper.ConvertDataTimeLong(dtEnd);
                }
                data.time_span = data.end_time - data.start_time;
                if (sate.Status == 1)
                {
                    run += data.time_span;
                }
                //newRun += data.time_span;
            }

            //var holdTimes = SliceManager.GetMachineStatusHold(machineIds, dtStart, dtEnd, sliceSates);
            //if (holdTimes != null && holdTimes.Any())
            //{
            //    foreach (var shutdownHoldTime in holdTimes)
            //    {
            //        if (shutdownHoldTime.Status == MachineRunningStatus.Running)
            //        {
            //            run += shutdownHoldTime.TimeSpan;
            //        }
            //    }
            //}

            foreach (var machineId in machineIds)
            {
                newRun += RestTimeManager.GetNewRun(machineId, dtStart, dtEnd, times);
            }
            return new OeeDetailEntity(oee1, oee2, oee3) { Run = run, Sum = newRun };
        }
    }
}
