
using System;
using System.Collections.Generic;
using FMSAdmin.Helpers.Formula;

namespace FMSAdmin.Models.Formula {
    public class FormulaData {
        public int SiteId { get; set; }
        public int FacilityTypeId { get; set; }
        public int FacilityCode { get; set; }
        public int FormulaId { get; set; }
        public string Formula { get; set; }
        public List<FormulaParameterData> Paramters { get; set; }
    };

    public class FormulaParameterData {
        public int SiteId { get; set; }
        public int FacilityTypeId { get; set; }
        public int FacilityCode { get; set; }
        public int FormulaId { get; set; }
        public string ParameterId { get; set; }

        public int ParameterFacilityCode { get; set; }
        public int ParameterPropertyId { get; set; }
    };

    public class CalculationResult {
        public DateTime DateTime { get; set; }
        public string ShortDateTime { get; set; }
        public double Value { get; set; }
        public double Percent { get; set; }
    };

    public class CalculationValue {
        public CalculationValue() {
        }

        public DateTime DateTime { get; set; }
        public double Value { get; set; }
    };

    public class CalculationValueBudget {
        public CalculationValueBudget() {
        }

        public DateTime DateTime { get; set; }
        public double Value { get; set; }
        public double Value2 { get; set; }
    };

    public class CalculationValueSType {
        public CalculationValueSType() {
        }

        public DateTime DateTime { get; set; }
        public double Value { get; set; }
        public int ServiceType { get; set; }
    };

    public class CalculationParameter {
        public MathParameterValue ParameterValue { get; set; }
        //public string FacilityCode { get; set; }
        //public int PropertyId { get; set; }
        public CalculationValue[] Values { get; set; }

        public DateTime SetValueFromIndex(int index) {
            var value = this.Values[index];

            this.ParameterValue.Value = (decimal)value.Value;
            return value.DateTime;
        }
    };

    public class CalculationLastResult {
        public DateTime DateTime { get; set; }
        public string ShortDateTime { get; set; }
        public double Value { get; set; }
        public double Percent { get; set; }
        public DateTime LastDateTime { get; set; }
        public string LastShortDateTime { get; set; }
        public double LastValue { get; set; }
        public double LastPercent { get; set; }
        public string DayOfWeek { get; set; }
    };

    public class ParameterBox {
        public DateTime DateTime { get; set; }

        Box[] boxes;
        public ParameterBox(CalculationParameter[] parameters) {
            this.boxes = new Box[parameters.Length];
            for (int i = 0; i < parameters.Length; i++) {
                var box = this.boxes[i] = new Box();
                box.parameter = parameters[i];
            }
        }

        public bool NextStage() {
            for (var i = 0; i < this.boxes.Length; i++) {
                var box = this.boxes[i];
                box.Set = false;
                if (box.Next() == false) {
                    return false;
                }
            }
            return true;
        }

        public bool Sync() {
            if (this.boxes == null || this.boxes.Length == 0) return false;


            var value = this.boxes[0].GetValue();
            if (value == null)
                return false;

            var dateTime = value.DateTime;

        Loop:
            for (var i = 0; i < this.boxes.Length; i++) {
                var box = this.boxes[i];
                if (box.Set) {
                    continue;
                }

                switch (box.Sync(dateTime)) {
                    case -1: // 없다. 더이상 계산이 필요 없다.
                        return false;
                    case 0:  // 동일한 것이 있다. 
                        box.Set = true;
                        break;
                    case 1:  // 초과한 시간이 있다. 
                        dateTime = box.GetValue().DateTime;
                        goto Loop;
                }
            }

            this.DateTime = dateTime;
            return true;
        }

        class Box {
            public enum IndexAtDateTimeResult {

            };
            public bool Set { get; set; }
            public int currentIndex = 0;
            public CalculationParameter parameter;
            public IndexAtDateTimeResult Result { get; set; }

            public Box() {
                Set = false;
            }

            public bool Next() {
                this.currentIndex++;
                return (this.currentIndex < parameter.Values.Length);
            }

            public int Sync(DateTime dateTime) {
                var values = parameter.Values;
                if (values != null) {
                    for (var i = currentIndex; i < values.Length; i++) {
                        if (values[i].DateTime == dateTime) {
                            this.currentIndex = i;
                            this.Setup();
                            return 0;
                        }

                        if (dateTime < values[i].DateTime) {
                            this.currentIndex = i;
                            return 1;
                        }
                    }
                }
                return -1;
            }

            public CalculationValue GetValue() {
                if (parameter.Values == null)
                    return null;
                if (parameter.Values.Length <= currentIndex)
                    return null;

                return parameter.Values[currentIndex];
            }
            public void Setup() {
                this.Set = true;
                this.parameter.SetValueFromIndex(currentIndex);
            }
        }
    }
}