using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Data;
using Foresight.Data;
using IronIntel.Contractor.Machines;

namespace IronIntel.Contractor.Maintenance
{
    public class IATCAlertsSyncService
    {
        private static bool isrunning = false;

        private static Dictionary<string, string> _AlertTypeMapping = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        public static void Start()
        {
            if (isrunning)
            {
                return;
            }
            isrunning = true;
            InitAlertTypeMapping();
            Thread thd = new Thread(DoWork);
            thd.Start();
        }

        public static void Stop()
        {
            isrunning = false;
        }

        private static void InitAlertTypeMapping()
        {
            _AlertTypeMapping.Clear();
            _AlertTypeMapping["FI-DTCJ1939"] = "FI - DTC";
            _AlertTypeMapping["FI-Jpod2"] = "FI - DTC";
            _AlertTypeMapping["Green-Inspect"] = "Green-Inspect";
            _AlertTypeMapping["INFO"] = "Info";
            _AlertTypeMapping["Info-Inspect"] = "Info-Inspect";
            _AlertTypeMapping["OTHER-Abnormality"] = "Red";
            _AlertTypeMapping["OTHER-Caution"] = "Yellow";
            _AlertTypeMapping["OTHER-OilSampleResult"] = "Oil Sample";
            _AlertTypeMapping["OTHER-PreventativeMaintenance"] = null;
            _AlertTypeMapping["RED"] = "Red";
            _AlertTypeMapping["Red-Inspect"] = "Red-Inspect";
            _AlertTypeMapping["YELLOW"] = "Yellow";
            _AlertTypeMapping["Yellow-Inspect"] = "Yellow-Inspect";
        }


        private static void DoWork()
        {
            const int SLEEPTIME = 60;
            while (isrunning)
            {
                DateTime dt1 = DateTime.Now;
                try
                {
                    IATCAlertsSyncService svc = new IATCAlertsSyncService();
                    svc.SyncAlerts();
                }
                catch
                {
                }
                TimeSpan sp = DateTime.Now - dt1;
                int delta = SLEEPTIME - Convert.ToInt32(sp.TotalSeconds);
                if (delta < 0)
                {
                    delta = 1;
                }
                Thread.Sleep(delta * 1000);
            }
        }

        private IATCAlertsSyncService()
        {

        }

        private Dictionary<long, machinedata> _Machines = new Dictionary<long, machinedata>();

        private machinedata GetMachinedata(long id)
        {
            const string SQL = "select MACHINEID,VIN,MACHINENAME,MACHINENAME2,MAKEID,MODELID,TYPEID from MACHINES where MACHINEID={0}";

            machinedata m = null;
            if (_Machines.TryGetValue(id, out m))
            {
                return m;
            }

            FISqlConnection db = SystemParams.GetDbInstance();
            DataTable tb = db.GetDataTableBySQL(SQL, id);
            if (tb.Rows.Count == 0)
            {
                _Machines.Add(id, null);
                return null;
            }

            m = new machinedata();
            m.ID = Convert.ToInt64(tb.Rows[0]["MACHINEID"]);
            m.Name = FIDbAccess.GetFieldString(tb.Rows[0]["MACHINENAME"], string.Empty);
            m.Name2 = FIDbAccess.GetFieldString(tb.Rows[0]["MACHINENAME2"], string.Empty);
            m.VIN = FIDbAccess.GetFieldString(tb.Rows[0]["VIN"], string.Empty);
            m.MakeID = FIDbAccess.GetFieldInt(tb.Rows[0]["MAKEID"], -1);
            m.ModelID = FIDbAccess.GetFieldInt(tb.Rows[0]["MODELID"], -1);
            m.TypeID = FIDbAccess.GetFieldInt(tb.Rows[0]["TYPEID"], -1);
            m.ModelName = MachineManagement.GetMachineModelName(m.ModelID);
            m.MakeName = MachineManagement.GetMachineMakeName(m.MakeID);
            m.TypeName = MachineManagement.GetMachineTypeName(m.TypeID);

            _Machines[id] = m;
            return m;
        }

        public void SyncAlerts()
        {
            const string SQL = "select top 100 * from IATCALERTS where ALERTID>(select isnull(max(IATCALERTID),-1) from ALERTS where SRC='LOCALTABLE_IATCALERTS') order by ALERTID";//process most 100 alerts each time

            FISqlConnection db = SystemParams.GetDbInstance();
            DataTable tb = db.GetDataTableBySQL(SQL);
            foreach (DataRow dr in tb.Rows)
            {
                long alertid = Convert.ToInt64(dr["ALERTID"]);
                try
                {
                    InsertData(db, dr);
                }
                catch (Exception ex)
                {
                    SystemParams.WriteLog("Error", GetType().FullName + ". DoWork()", "Sync IATCALERTS failed: " + alertid, ex.ToString());
                }
            }
        }

        private void InsertData(FISqlConnection db, DataRow dr)
        {
            const string SQL = "if not exists(select 1 from ALERTS where SRC='LOCALTABLE_IATCALERTS' and IATCALERTID={0}) "
                + "insert into ALERTS(ALERTTIME_UTC,ALERTTYPE,ALERTTITLE,ALERTDESC,MACHINEID,VIN,MACHINENAME,MODELID,MODELNAME,"
                + "MAKEID,MAKENAME,TYPEID,TYPENAME,ENGINGHOURS,LATITUDE,LONGITUDE,LOCDATE_UTC,SRC,INSERTTIME,REFID,IATCALERTID) "
                + " values({1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},'LOCALTABLE_IATCALERTS',getdate(),{0},{0})";

            long machineid = Convert.IsDBNull(dr["MACHINEID"]) ? -1 : Convert.ToInt64(dr["MACHINEID"]);
            machinedata m = GetMachinedata(machineid);
            if (m == null)
            {
                m = new machinedata();
                m.ID = machineid;
                m.VIN = FIDbAccess.GetFieldString(dr["VIN"], string.Empty);
                m.Name2 = FIDbAccess.GetFieldString(dr["MACHINENAME"], string.Empty);
                m.MakeName = FIDbAccess.GetFieldString(dr["MAKE"], string.Empty);
                m.ModelName = FIDbAccess.GetFieldString(dr["MODEL"], string.Empty);
                m.TypeName = FIDbAccess.GetFieldString(dr["MACHINETYPE"], string.Empty);
            }
            long alertid = Convert.ToInt64(dr["ALERTID"]);
            double hours = FIDbAccess.GetFieldDouble(dr["ENGINEHOURS"], 0);
            double lat = FIDbAccess.GetFieldDouble(dr["CUR_LATITUDE"], 0);
            double lon = FIDbAccess.GetFieldDouble(dr["CUR_LONGITUDE"], 0);
            DateTime? locdate = FIDbAccess.GetNullableDateTime(dr["LOCATIONTIME_UTC"]);
            DateTime? alerttime = FIDbAccess.GetNullableDateTime(dr["RECEIVEDDATE"]);
            string title = FIDbAccess.GetFieldString(dr["ALERTTITLE"], string.Empty);
            string desc = FIDbAccess.GetFieldString(dr["ALERTDESC"], string.Empty);
            string alerttype = FIDbAccess.GetFieldString(dr["ALERTTYPE"], string.Empty);
            alerttype = DetermineAlertType(alerttype.Trim());
            if (alerttype == null)
                return;
            db.ExecSQL(SQL, alertid, alerttime, alerttype, title, desc, m.ID, m.VIN, m.CustName, m.ModelID, m.ModelName, m.MakeID, m.MakeName, m.TypeID, m.TypeName, hours, lat, lon, locdate);
        }

        private string DetermineAlertType(string alerttype)
        {
            if (!string.IsNullOrEmpty(alerttype))
            {
                string temp = alerttype.Trim().Replace(" ", "");
                if (_AlertTypeMapping.ContainsKey(temp))
                    alerttype = _AlertTypeMapping[temp];
            }
            else
                alerttype = "";
            return alerttype;
        }

        class machinedata
        {
            public long ID = 0;
            public string VIN = string.Empty;
            public string Name = string.Empty;
            public string Name2 = string.Empty;
            public int MakeID = -1;
            public int ModelID = -1;
            public int TypeID = -1;
            public string MakeName = string.Empty;
            public string ModelName = string.Empty;
            public string TypeName = string.Empty;

            public string CustName
            {
                get
                {
                    if (!string.IsNullOrWhiteSpace(Name2))
                    {
                        return Name2;
                    }
                    return string.IsNullOrWhiteSpace(Name) ? VIN : Name;
                }
            }
        }
    }
}
