using iBemsDataService.Model;
using Quartz;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using System.Web;
using System.Diagnostics;
using DevExpress.Office.Utils;
using System.Text;
using System.Text.RegularExpressions;
using iBemsDataService.Util;
using iBemsDataService.Controllers.Bems.Formula;
using iBemsDataService.Controllers.Bems.Common;

namespace iBemsDataService.Controllers.Bems.ScheduledTask
{
    public class ControlBems : IJob
    {
        private iBemsEntities db = new iBemsEntities();
        private static Regex regexParameter = new Regex(@"\b[A-Z]\b", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
        private static Regex regexFunction = new Regex(@"\$([\w]+).+\$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);

        public double GetTempSetValue(int month, CmFacilityTempSet ft)
        {
            switch (month)
            {
                case 1: return ft.T1;
                case 2: return ft.T2;
                case 3: return ft.T3;
                case 4: return ft.T4;
                case 5: return ft.T5;
                case 6: return ft.T6;
                case 7: return ft.T7;
                case 8: return ft.T8;
                case 9: return ft.T9;
                case 10: return ft.T10;
                case 11: return ft.T11;
                case 12: return ft.T12; 
            }
            return 0;
        }

        public CmFacility GetCmFacility(CmFacilityTempSet tempset)
        {
            var FTS = from f in db.CmFacility where f.SiteId == tempset.SiteId && f.FacilityCode == tempset.FacilityCode select f;
            return (CmFacility)FTS.First();
        }

        public void Execute( IJobExecutionContext context )
        {
            var today = DateTime.Now;
            //var tomorrow = today.AddDays( 1 );
            //BemsFormulaController BFC = new BemsFormulaController();

            using (var transaction = new TransactionScope())
            {
                var site = from s in db.CmSite select s;
                List<CmSite> sitelist = site.ToList();
                foreach (CmSite s in sitelist)
                {
                    if (s.IsControlSchedule == true && s.ScheduleCheckHour == today.Hour && today.Minute == 0)
                    {
                        var FTS = from f in db.CmFacilityTempSet where f.SiteId == s.SiteId select f;
                        List<CmFacilityTempSet> list = FTS.ToList();

                        foreach (CmFacilityTempSet ts in list)
                        {
                            CmFacility facility = GetCmFacility(ts);
                            var queryFormula = from f in db.BemsFormula
                                where f.SiteId == ts.SiteId && f.FacilityTypeId == facility.FacilityTypeId && f.FacilityCode == ts.FacilityCode && f.FormulaId == 20
                                select f;
                            if (queryFormula == null || queryFormula.Count() <= 0) continue;

                            BemsFormula formula = (BemsFormula)queryFormula.First();
                            ArrayList parameters = new ArrayList();
                            MathCalculator calculator = new MathCalculator();
                            if (false == calculator.Compile(formula.Formula))
                            {
                                throw new Exception("Failed to compile formula: " + formula.Formula);
                            }
                            var match = regexParameter.Match(formula.Formula);
                            if (match.Success)
                            {
                                var queryParameters = db.BemsFormulaParameter.Where(x =>
                                    x.SiteId == ts.SiteId && x.FacilityTypeId == facility.FacilityTypeId &&
                                    x.FacilityCode == ts.FacilityCode && x.FormulaId == 20);
                                if (queryParameters.Any() == false)
                                {
                                    //; throw new Exception(string.Format("Not Found 2222 Parameters: {0},{1},{2},{3}", ts.SiteId, 99, ts.FacilityCode, 20));
                                    ;
                                }
                                foreach (var p in queryParameters)
                                {
                                    var control = new BemsControlPointHistory
                                    {
                                        SiteId = ts.SiteId,
                                        //FacilityTypeId = 99,
                                        FacilityTypeId = facility.FacilityTypeId,
                                        FacilityCode = p.ParameterFacilityCode,
                                        PropertyId = p.ParameterPropertyId,
                                        CreateDateTime = today,
                                        ControlValue = GetTempSetValue(today.Month, ts),
                                        WriteServiceName = null,
                                        ActionDateTime = null
                                    };
                                    db.BemsControlPointHistory.Add(control);
                                    db.SaveChanges();
                                }
                            }
                        }
                    }
                }
                transaction.Complete();
            }   
        }

        private void InsertWorkOrder( FmsWorkRequest workRequest , List<FmsWorkScheduleToFacility> facilities )
        {
            var workOrder = new FmsWorkOrder
            {
                SiteId = workRequest.SiteId ,
                WorkRequestId = workRequest.WorkRequestId ,
                BusinessFieldId = workRequest.BusinessFieldId ,


                OrderUserId = workRequest.RequestUserId ,
                OrderDate = DateTime.Now.Date ,

                Title = workRequest.Title ,
                Content = workRequest.Content ,

                StartWorkDate = workRequest.StartWorkDate 
            };

            workOrder = db.FmsWorkOrder.Add( workOrder );

            foreach( var f in facilities )
            {
                db.FmsWorkOrderToFacility.Add( new FmsWorkOrderToFacility
                {
                    SiteId = f.SiteId ,
                    WorkRequestId = workOrder.WorkRequestId ,
                    FacilityCode = f.FacilityCode
                } );
            }

            workRequest.WorkProgressId = (short)WorkProgress.WORK_STANDBY;

            db.SaveChanges();
        }
    }
}