using Foresight.Data;
using Foresight.ServiceModel;
using IronIntel.Contractor.Machines;
using IronIntel.Contractor.Maintenance;
using IronIntel.Contractor.MapView;
using IronIntel.Contractor.Users;
using IronIntel.Services.Business.Admin;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IronIntel.Contractor.Security
{
    public class CurfewManagement
    {
        public static CurfewInfo[] GetCurfews(string sessionid, string searchtext, FISqlConnection db = null)
        {
            const string SQL = "select CURFEWID,TITLE,DAY,STARTTIME,ENDTIME,ISENABLED,DATEADDED_UTC,ADDBY,DATEUPDATED_UTC,UPDATEDBY,TIMEPERIOD from CURFEW where ISENABLED=1";

            List<CurfewInfo> list = new List<CurfewInfo>();
            if (db == null)
                db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL);
            if (dt.Rows.Count > 0)
            {
                UserInfo[] users = UserManagement.GetUsers();
                foreach (DataRow dr in dt.Rows)
                {
                    CurfewInfo ci = ConvertToCurfewInfo(dr);
                    if (string.IsNullOrWhiteSpace(searchtext)
                        || Helper.Contains(ci.Title, searchtext))
                        list.Add(ci);
                }
            }
            return list.ToArray();
        }

        public static CurfewInfo GetCurfewInfo(string curfewid, FISqlConnection db = null)
        {
            const string SQL = "select CURFEWID,TITLE,DAY,STARTTIME,ENDTIME,ISENABLED,DATEADDED_UTC,ADDBY,DATEUPDATED_UTC,UPDATEDBY,TIMEPERIOD from CURFEW where ISENABLED=1 and CURFEWID={0}";

            List<CurfewInfo> list = new List<CurfewInfo>();
            if (db == null)
                db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL, curfewid);
            CurfewInfo ci = new CurfewInfo();
            if (dt.Rows.Count > 0)
            {
                ci = ConvertToCurfewInfo(dt.Rows[0]);
            }
            return ci;
        }


        public static void SaveCurfew(CurfewInfo ci, string useriid, FISqlConnection db = null)
        {
            const string SQL = @"if exists(select 1 from CURFEW where CURFEWID={0}) update CURFEW set TITLE={1},DAY={2},STARTTIME={3},ENDTIME={4},DATEUPDATED_UTC=GETUTCDATE(),UPDATEDBY={5},TIMEPERIOD={6} where CURFEWID={0} 
            else insert CURFEW(CURFEWID,TITLE,DAY,STARTTIME,ENDTIME,ISENABLED,DATEADDED_UTC,ADDBY,DATEUPDATED_UTC,UPDATEDBY,TIMEPERIOD) values({0},{1},{2},{3},{4},1,GETUTCDATE(),{5},GETUTCDATE(),{5},{6})";

            const string SQL_C = "select COUNT(1) from CURFEW where CURFEWID!={0} and TITLE={1} and ISENABLED=1";

            if (db == null)
                db = SystemParams.GetDbInstance();
            object obj = db.GetRC1BySQL(SQL_C, ci.CurfewID, ci.Title);
            if (Convert.ToInt32(obj) > 0)
            {
                throw new Exception("The curfew title must be unique.");
            }

            string timeperiodStr = "";
            if (ci.TimePeriods == null || ci.TimePeriods.Length <= 0)
                throw new Exception("Period cannot be empty.");

            foreach (StringKeyValue item in ci.TimePeriods)
            {
                int st = Convert.ToInt32(item.Tag1 + item.Tag2);
                int et = Convert.ToInt32(item.Tag3 + item.Tag4);
                if (st >= et)
                    throw new Exception("End Time must be later than Start Time.");

                string str = item.Tag1 + ":" + item.Tag2 + "-" + item.Tag3 + ":" + item.Tag4;
                if (string.IsNullOrWhiteSpace(timeperiodStr))
                    timeperiodStr = str;
                else
                    timeperiodStr = timeperiodStr + "," + str;
            }


            db.ExecSQL(SQL, ci.CurfewID, ci.Title, ci.Day, ci.StartTime, ci.EndTime, useriid, timeperiodStr);

        }

        public static void DeleteCurfew(string curfewid, FISqlConnection db = null)
        {
            const string SQL = @"update CURFEW set ISENABLED=0 where CURFEWID={0}";
            if (db == null)
                db = SystemParams.GetDbInstance();
            db.ExecSQL(SQL, curfewid);
        }

        public static MaintenanceMachineInfo[] GetCurfewMachinesByID(string curfewid, FISqlConnection db = null)
        {
            const string SQL = @"select a.RELATEDID as MACHINEID,b.MACHINENAME,b.MACHINENAME2,b.VIN,b.MAKEID,b.MODELID,b.TYPEID,b.HIDE,ISNULL(b.ENGINEHOURS,0) as ENGINEHOURS,
                    ISNULL(b.ODOMETER,0) as ODOMETER,ISNULL(b.ODOMETERUOM,'Mile') AS ODOMETERUOM from RELATIONSHIP a,MACHINES b 
                    where a.RELATEDID=b.MACHINEID and a.RELATIONSHIPTYPEID='CurfewToMachine' and a.REMOVED<>1 and a.PRIMARYID={0}";

            if (db == null)
                db = SystemParams.GetDbInstance();
            DataTable tb = db.GetDataTableBySQL(SQL, curfewid);
            if (tb.Rows.Count == 0)
            {
                return new MaintenanceMachineInfo[0];
            }
            MachineManagement.RefreshBaseData();
            MachineMake[] makes = MachineManagement.GetMachineMakes();
            MachineModel[] models = MachineManagement.GetMachineModels();
            MachineType[] types = MachineManagement.GetMachineTypes();
            List<MaintenanceMachineInfo> ls = new List<MaintenanceMachineInfo>();
            foreach (DataRow dr in tb.Rows)
            {
                MaintenanceMachineInfo mi = MaintenanceManagement.ConvertToMaintenanceMachineInfo(dr, makes, models, types);
                ls.Add(mi);
            }
            return ls.ToArray();

        }

        public static void SaveCurfewMachines(string curfewid, string contractorid, string[] machineids, FISqlConnection db)
        {
            const string SQL_R = "update RELATIONSHIP set REMOVEDON=GETUTCDATE(),REMOVED=1 where RELATIONSHIPTYPEID='CurfewToMachine' and REMOVED<>1 and PRIMARYID={0}";
            const string SQL = @"if exists(select 1 from RELATIONSHIP where RELATIONSHIPTYPEID='CurfewToMachine' and PRIMARYID={0} and RELATEDID={1}) update RELATIONSHIP
 set REMOVEDON=null,REMOVED=0 where RELATIONSHIPTYPEID='CurfewToMachine' and PRIMARYID={0} and RELATEDID={1} else insert into RELATIONSHIP
 (RELATIONSHIPID,RELATIONSHIPTYPEID,CONTRACTORID,PRIMARYID,RELATEDID,ADDEDON) values({3},'CurfewToMachine',{2},{0},{1},GETUTCDATE())";

            if (db == null)
                db = SystemParams.GetDbInstance();
            db.ExecSQL(SQL_R, curfewid);

            foreach (var mid in machineids)
            {
                db.ExecSQL(SQL, curfewid, mid, contractorid, Guid.NewGuid().ToString());
            }
        }

        private static CurfewInfo ConvertToCurfewInfo(DataRow dr)
        {
            CurfewInfo ci = new CurfewInfo();
            ci.CurfewID = FIDbAccess.GetFieldString(dr["CURFEWID"], string.Empty);
            ci.Title = FIDbAccess.GetFieldString(dr["TITLE"], string.Empty);
            ci.Day = FIDbAccess.GetFieldString(dr["DAY"], string.Empty);
            ci.StartTime = FIDbAccess.GetFieldString(dr["STARTTIME"], string.Empty);
            ci.EndTime = FIDbAccess.GetFieldString(dr["ENDTIME"], string.Empty);
            ci.IsEnabled = FIDbAccess.GetFieldInt(dr["ISENABLED"], 0);
            ci.DateAdded = FIDbAccess.GetFieldDateTime(dr["DATEADDED_UTC"], DateTime.MinValue);
            ci.DateAdded = ci.DateAdded.AddHours(SystemParams.GetHoursOffset());
            ci.AddBy = FIDbAccess.GetFieldString(dr["ADDBY"], string.Empty);
            ci.DateUpdated = FIDbAccess.GetFieldDateTime(dr["DATEUPDATED_UTC"], DateTime.MinValue);
            ci.DateUpdated = ci.DateUpdated.AddHours(SystemParams.GetHoursOffset());
            ci.UpdatedBy = FIDbAccess.GetFieldString(dr["UPDATEDBY"], string.Empty);
            ci.TimePeriod = FIDbAccess.GetFieldString(dr["TIMEPERIOD"], string.Empty);
            if (!string.IsNullOrWhiteSpace(ci.TimePeriod))
            {
                List<StringKeyValue> list = new List<StringKeyValue>();
                string[] periods = ci.TimePeriod.Split(',');
                foreach (string pd in periods)
                {
                    StringKeyValue kv = new StringKeyValue();
                    string[] time = pd.Split('-');
                    string[] starttime = time[0].Split(':');
                    string[] endtime = time[1].Split(':');
                    kv.Tag1 = starttime[0];
                    kv.Tag2 = starttime[1];
                    kv.Tag3 = endtime[0];
                    kv.Tag4 = endtime[1];
                    list.Add(kv);
                }
                ci.TimePeriods = list.ToArray();
            }
            else
                ci.TimePeriods = new StringKeyValue[0];
            return ci;
        }



        public static JobSiteViewItem[] GetCurfewJobsitesByID(string curfewid, FISqlConnection db = null)
        {
            const string SQL = @"select a.RELATEDID as JOBSITEID,JOBSITENAME,LATITUDE,LONGITUDE ,RADIUS,RADUIS_UOM,b.CONTRACTORID,COLOR,NOTES,STARTDATE,ENDDATE,POLYGON from RELATIONSHIP a,JOBSITES b 
                    where a.RELATIONSHIPTYPEID='CurfewToJobsite' and a.REMOVED<>1 and a.RELATEDID=b.JOBSITEID and a.PRIMARYID={0}";
            if (db == null)
                db = SystemParams.GetDbInstance();
            DataTable tb = db.GetDataTableBySQL(SQL, curfewid);
            if (tb.Rows.Count == 0)
            {
                return new JobSiteViewItem[0];
            }
            List<JobSiteViewItem> ls = new List<JobSiteViewItem>();
            foreach (DataRow dr in tb.Rows)
            {
                JobSiteViewItem js = ConvertToJobSiteViewItem(dr);
                ls.Add(js);
            }
            return ls.ToArray();

        }

        public static void SaveCurfewJobsites(string curfewid, string contractorid, string[] jobsiteids, FISqlConnection db = null)
        {
            const string SQL_R = "update RELATIONSHIP set REMOVEDON=GETUTCDATE(),REMOVED=1 where RELATIONSHIPTYPEID='CurfewToJobsite' and REMOVED<>1 and PRIMARYID={0}";
            const string SQL = @"if exists(select 1 from RELATIONSHIP where RELATIONSHIPTYPEID='CurfewToJobsite' and PRIMARYID={0} and RELATEDID={1}) update RELATIONSHIP
 set REMOVEDON=null,REMOVED=0 where RELATIONSHIPTYPEID='CurfewToJobsite' and PRIMARYID={0} and RELATEDID={1} else insert into RELATIONSHIP
 (RELATIONSHIPID,RELATIONSHIPTYPEID,CONTRACTORID,PRIMARYID,RELATEDID,ADDEDON) values({3},'CurfewToJobsite',{2},{0},{1},GETUTCDATE())";

            if (db == null)
                db = SystemParams.GetDbInstance();
            db.ExecSQL(SQL_R, curfewid);

            foreach (var mid in jobsiteids)
            {
                db.ExecSQL(SQL, curfewid, mid, contractorid, Guid.NewGuid().ToString());
            }
        }
        private static JobSiteViewItem ConvertToJobSiteViewItem(DataRow dr)
        {
            JobSiteViewItem js = new JobSiteViewItem();
            long JobSiteId = FIDbAccess.GetFieldInt(dr["JOBSITEID"], 0);
            js.ID = FIDbAccess.GetFieldInt(dr["JOBSITEID"], 0);
            js.Name = FIDbAccess.GetFieldString(dr["JOBSITENAME"], string.Empty);
            js.Latitude = FIDbAccess.GetFieldDouble(dr["LATITUDE"], 0);
            js.Longitude = FIDbAccess.GetFieldDouble(dr["LONGITUDE"], 0);
            js.Radius = FIDbAccess.GetFieldDouble(dr["RADIUS"], 0);
            js.Radius_UOM = FIDbAccess.GetFieldString(dr["RADUIS_UOM"], string.Empty);
            if (string.IsNullOrWhiteSpace(js.Radius_UOM))
                js.Radius_UOM = "Mile";
            js.ContractorID = FIDbAccess.GetFieldString(dr["CONTRACTORID"], string.Empty);
            //js.ColorString = FIDbAccess.GetFieldString(dr["COLOR"], string.Empty);
            //System.Drawing.Color color = System.Drawing.Color.Orange;
            //try
            //{
            //    color = System.Drawing.ColorTranslator.FromHtml(js.ColorString);
            //}
            //catch
            //{
            //}
            //js.Color = new IIColor() { Alpha = color.A, Red = color.R, Green = color.G, Blue = color.B };

            js.Notes = FIDbAccess.GetFieldString(dr["NOTES"], string.Empty);
            js.StartDate = FIDbAccess.GetFieldDateTime(dr["STARTDATE"], DateTime.MinValue);
            js.EndDate = FIDbAccess.GetFieldDateTime(dr["ENDDATE"], DateTime.MinValue);
            return js;
        }

        /// <summary>
        /// 获取机器Curfew和机器的对应关系
        /// </summary>
        /// <returns></returns>
        public static Dictionary<int, List<string>> GetCurfewMachines(FISqlConnection db)
        {
            const string SQL_C = "select PRIMARYID,RELATEDID from RELATIONSHIP where RELATIONSHIPTYPEID='CurfewToMachine' and REMOVED<>1";

            Dictionary<int, List<string>> result = new Dictionary<int, List<string>>();
            if (db == null)
                db = SystemParams.GetDbInstance();
            DataTable tb = db.GetDataTableBySQL(SQL_C);

            foreach (DataRow dr in tb.Rows)
            {
                int machineid = FIDbAccess.GetFieldInt(dr["RELATEDID"], 0);
                string curfewid = FIDbAccess.GetFieldString(dr["PRIMARYID"], "");
                if (!result.ContainsKey(machineid))
                    result[machineid] = new List<string>();
                result[machineid].Add(curfewid);
            }
            return result;
        }
    }
}

