using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using parkMonitor.DataBase;
using parkMonitor.Database2;
using System.Configuration;
using parkMonitor.entity;
using parkMonitor.LOG;
using parkMonitor.server.uiLogServer;
using parkMonitor.controlPanel;
using parkMonitor.model;

namespace parkMonitor.server.CoreThread
{
    /// <summary>
    /// 车位分配
    /// </summary>
    public class ParkingSpaceManager
    {
        public Dictionary<int, Parking_Space> parkingSpaceStatusMap = new Dictionary<int, Parking_Space>();
        private Dictionary<int, Parking_Space> lps = new Dictionary<int, Parking_Space>();
        private double xWeight;
        private double yWeight;
        private double zWeight;
        public static ParkingSpaceManager ins = null;
        public static int garageID;
        /// <summary>
        /// 初始化车位缓存
        /// </summary>
        public bool InitParkingSpace()
        {
            if (ins != null)
            {
                lock (ins.parkingSpaceStatusMap)
                {
                    parkingSpaceStatusMap = new Dictionary<int, Parking_Space>();
                    DBOperation oper = new DBOperation();
                    garageID = 0;
                    try
                    {
                        garageID = Int32.Parse(ConfigurationManager.AppSettings["garageID"]);
                    }
                    catch { UILogServer.ins.error("无法获取车库ID，请检查配置"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "无车库ID相关配置"); return false; }
                    try
                    {
                        xWeight = Convert.ToDouble(ConfigurationManager.AppSettings["xWeight"]);
                        yWeight = Convert.ToDouble(ConfigurationManager.AppSettings["yWeight"]);
                        zWeight = Convert.ToDouble(ConfigurationManager.AppSettings["zWeight"]);
                    }
                    catch { UILogServer.ins.error("无法获得车位权重，请检查配置"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "无法获得车位权重"); return false; }
                    int i = 0;
                    if (garageID != 0)
                    {
                        while (((parkingSpaceStatusMap == null || parkingSpaceStatusMap.Count==0) && i++ < 2))
                        {
                            parkingSpaceStatusMap = oper.GetAllParkingSpace(EntityForCore.remoteBQ, garageID);
                        }
                        if (i >= 2)
                        {
                            parkingSpaceStatusMap = null;
                            return false;
                        }
                    }
                    else 
                    {
                        parkingSpaceStatusMap = null;
                        return false;
                    }
                    //if (garageID != 0)
                    //{
                    //    parkingSpaceStatusMap = oper.GetAllParkingSpace(EntityForCore.remoteBQ, garageID);
                    //}
                    //else
                    //{
                    //    parkingSpaceStatusMap = null;
                    //    return false;
                    //}
                    //车位校验，与PLC车位数据核对
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.INFO, "车位表缓存成功");
                    return true;
                }
            }
            else { return false; }
        }
        /// <summary>
        /// 最短路径分配，根据车位位置及状态分配目标车位，返回Parking Space的ID
        /// </summary>
        /// <param name="pt_Ent"></param>
        /// <param name="booking">进行预约，提前分配车位</param>
        /// <param name="queueCmd"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public Parking_Space MallocParkingSpace(CEntrance pt_Ent, Command queueCmd, bool booking, out int count)
        {
            count = 0;
            if (ins != null)
            {
                lock (ins.parkingSpaceStatusMap)
                {
                    //获取车位前准备
                    if (parkingSpaceStatusMap == null || zWeight == 0)
                    {
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "车辆表缓存或车位权重初始化异常");
                        return null;
                    }
                    //获取空闲车位和判断是否已预约车位
                    if (lps != null)
                    {
                        lps.Clear();
                    }
                    else
                    {
                        lps = new Dictionary<int, Parking_Space>();
                    }
                    Dictionary<int, Parking_Space>.Enumerator enumer = parkingSpaceStatusMap.GetEnumerator();
                    Parking_Space temp = null;
                    string log = "[";
                    while (enumer.MoveNext())
                    {
                        if (enumer.Current.Value != null)
                        {
                            if (enumer.Current.Value.parkingSpaceState == 0)
                            {
                                lps.Add(enumer.Current.Key, enumer.Current.Value);
                                //输出空闲车位
                                log += enumer.Current.Key.ToString() + ",";
                            }
                            else if (enumer.Current.Value.parkingSpaceState == 2 && enumer.Current.Value.licence == queueCmd.LicenseNum)
                            {
                                temp = (Parking_Space)(enumer.Current.Value.Clone());
                            }
                        }
                    }
                    
                    if (temp != null && !booking)
                    {
                        //分配已预约的车位后将该车位置为占用
                        parkingSpaceStatusMap[temp.parkingSpaceID].parkingSpaceState = 1;
                        return temp;
                    }
                    //无空闲车位则退出
                    if (lps.Count == 0)
                    {
                        return null;
                    }
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, log + "]");
                    //分配车位
                    Parking_Space rps = new Parking_Space();
                    float min_dis_sq = 100000000; //初始10000单位距离
                    Dictionary<int, Parking_Space>.Enumerator enumer2 = lps.GetEnumerator();
                    while (enumer2.MoveNext())
                    {
                        if (enumer2.Current.Value != null)
                        {
                            float deltaX = (enumer2.Current.Value.parkingSpaceX - pt_Ent.parkingEntX) * (float)xWeight;
                            float deltaY = (enumer2.Current.Value.parkingSpaceY - pt_Ent.parkingEntY) * (float)yWeight;
                            float deltaZ = (enumer2.Current.Value.parkingSpaceZ - pt_Ent.parkingEntZ) * (float)zWeight;
                            float dist_sq = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
                            if (dist_sq < min_dis_sq)
                            {
                                min_dis_sq = dist_sq;
                                rps = enumer2.Current.Value;
                            }
                        }
                    }
                    count = lps.Count - 1;
                    //分配后将该车位置为占用或已预约
                    if (!booking)
                    {
                        parkingSpaceStatusMap[rps.parkingSpaceID].parkingSpaceState = 1;
                    }
                    else
                    {
                        parkingSpaceStatusMap[rps.parkingSpaceID].parkingSpaceState = 2;
                        parkingSpaceStatusMap[rps.parkingSpaceID].licence = queueCmd.LicenseNum;
                    }
                    return rps;
                }
            }
            return null;
        }
        /// <summary>
        /// 取车完成将该车位释放
        /// </summary>
        /// <param name="parkingSpaceID"></param>
        /// <returns></returns>
        public bool SetParkingSpace(int parkingSpaceID, int status)
        {
            if (CheckIfSpaceExist(parkingSpaceID))
            {
                if (parkingSpaceStatusMap[parkingSpaceID].parkingSpaceState != status)
                {
                    parkingSpaceStatusMap[parkingSpaceID].parkingSpaceState = status;
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "车位ID：" + parkingSpaceStatusMap[parkingSpaceID].parkingSpaceID + "置为" + status);
                    //清空该车位号牌
                    if (status == 0)
                    {
                        parkingSpaceStatusMap[parkingSpaceID].licence = "";
                    }
                    return true;
                }
                else { return false; }
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 判断车位是否存在
        /// </summary>
        /// <param name="parkingSpaceID"></param>
        /// <returns></returns>
        public bool CheckIfSpaceExist(int parkingSpaceID)
        {
            if (parkingSpaceStatusMap != null && parkingSpaceStatusMap.ContainsKey(parkingSpaceID))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 获取空闲车位数
        /// </summary>
        /// <returns></returns>
        public int GetFreeSpaceCount()
        {
            int count = 0;
            if (parkingSpaceStatusMap != null)
            {
                Dictionary<int, Parking_Space>.Enumerator enumer = parkingSpaceStatusMap.GetEnumerator();
                while (enumer.MoveNext())
                {
                    if (enumer.Current.Value != null && enumer.Current.Value.parkingSpaceState == 0) { count += 1; }
                }
            }
            return count;
        }
        /// <summary>
        /// 释放已预约占用的车位
        /// </summary>
        /// <param name="license"></param>
        /// <returns></returns>
        public bool CancleBooking(string license)
        {
            Dictionary<int, Parking_Space>.Enumerator enumer = parkingSpaceStatusMap.GetEnumerator();
            Parking_Space temp = null;
            while (enumer.MoveNext())
            {
                if (enumer.Current.Value != null && enumer.Current.Value.parkingSpaceState == 2 && enumer.Current.Value.licence == license)
                {
                    temp = (Parking_Space)(enumer.Current.Value.Clone());
                }
            }
            if (temp != null)
            {
                parkingSpaceStatusMap[temp.parkingSpaceID].parkingSpaceState = 0;
                parkingSpaceStatusMap[temp.parkingSpaceID].licence = "";
                return true;
            }
            else { return false; }
        }
    }

    public class CEntrance
    {
        public int parkingEntX { get; set; }
        public int parkingEntY { get; set; }
        public int parkingEntZ { get; set; }
        public CEntrance(int entX, int entY, int entZ)
        {
            parkingEntX = entX;
            parkingEntY = entY;
            parkingEntZ = entZ;
        }
        public CEntrance()
            : this(0, 0, 0)
        {

        }
    }

    /// <summary>
    /// 车位单元
    /// </summary>
    public class Parking_Space : ICloneable
    {
        public static Object spaceLock = new Object();
        public static Object RecordLock = new Object();
        public int parkingSpaceID { get; set; }
        //public float parkingSpaceWeight { get; set; }
        public int garageID { get; set; }
        //public int parkingSpaceStatement { get; set; }
        public int parkingSpaceX { get; set; }
        public int parkingSpaceY { get; set; }
        public int parkingSpaceZ { get; set; }
        //  0.空闲    1.占用    2.预约
        public int parkingSpaceState { get; set; }
        public string licence { get; set; }
        public object Clone()
        {
            Parking_Space ps_new = new Parking_Space();
            ps_new.parkingSpaceID = parkingSpaceID;
            ps_new.garageID = garageID;
            ps_new.parkingSpaceState = parkingSpaceState;
            ps_new.parkingSpaceX = parkingSpaceX;
            ps_new.parkingSpaceY = parkingSpaceY;
            ps_new.parkingSpaceZ = parkingSpaceZ;
            ps_new.licence = licence;
            return ps_new;
        }
    }

    /// <summary>
    /// 缓冲位管理
    /// </summary>
    public class ParkingBufferManager
    {
        public static ParkingBufferManager ins { get; set; }
        public int bufferCount { get; set; }
        private int bufferAddress = 0, completeStatusAddress = 0;
        public bool checkedAuto { get; set; }
        public List<ParkingBuffer> bufferList = null;
        public bool InitParkingBuffers()
        {
            checkedAuto = false;
            bufferList = new List<ParkingBuffer>();
            try
            {
                bufferCount = Int32.Parse(ConfigurationManager.AppSettings["bufferCount"]);
                bufferAddress = Int32.Parse(ConfigurationManager.AppSettings["bufferAddress"]);
                completeStatusAddress = Int32.Parse(ConfigurationManager.AppSettings["completeStatusAddress"]);
                IEquipments plc = null;
                List<PLCNode> pList = null;
                while (plc == null)
                {
                    plc = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.PLC);
                }
                pList = ((PLCMessage)plc.GetMessage()).originalPlcList;
                //while (pList.Count() == 0) { pList = ((PLCMessage)plc.GetMessage()).originalPlcList; }
                //根据plc中数据初始化缓冲位
                for (int i = 0; i < bufferCount; i++)
                {
                    for (int j = 0; j < pList.Count; j++)
                    {
                        if (pList[j].Address == (bufferAddress + i).ToString())
                        {
                            if (pList[j].Value == "1")
                            {
                                bufferList.Add(new ParkingBuffer(i + 1, true));
                                break;
                            }
                            else if (pList[j].Value == "0")
                            {
                                bufferList.Add(new ParkingBuffer(i + 1, false));
                                break;
                            }
                            else
                            {
                                UILogServer.ins.error("缓冲位数据异常，请检查plc相关数据");
                                return false;
                            }
                        }
                    }
                }
                if(bufferList.Count!= bufferCount)
                {
                    UILogServer.ins.error("缓冲位数据异常，请检查plc相关数据");
                    return false;
                }
                //UILogServer.ins.warn("请手动确认缓冲位状态");
                Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "初始化缓冲位成功");
                checkedAuto = true;
                return true;
            }
            catch { Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "初始化缓冲位失败"); return false; }
        }
        public ParkingBuffer MallocParkingBuffer(int numMachineID)
        {
            if (!checkedAuto)
                return null;
            int min_dis_sq = 2500; //初始默认缓冲位距号牌ID 50 个单位
            ParkingBuffer allocatedPB = null;
            for (int i = 0; i < bufferCount; i++)
            {
                if (!bufferList[i].occupied)
                {
                    int diff_dis = bufferList[i].bufferID - numMachineID;
                    if (min_dis_sq > diff_dis * diff_dis)
                    {
                        min_dis_sq = diff_dis * diff_dis;
                        allocatedPB = (ParkingBuffer)bufferList[i].Clone();
                    }
                }
            }
            if (allocatedPB != null && allocatedPB.bufferID > 0)
            {
                bufferList[allocatedPB.bufferID - 1].occupied = true;
                return allocatedPB;
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 暂时取车完成释放缓冲位
        /// </summary>
        /// <param name="parkingSpaceID"></param>
        /// <returns></returns>
        public bool ReleaseParkingBuffer(int bufferID)
        {
            if (CheckIfBufferExist(bufferID))
            {
                bufferList[bufferID - 1].occupied = false;
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 判断缓冲位是否存在
        /// </summary>
        /// <param name="parkingSpaceID"></param>
        /// <returns></returns>
        public bool CheckIfBufferExist(int bufferID)
        {
            if (bufferList != null && bufferList.Count >= bufferID && bufferID > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool SetParkingBuffer(int parkingBufferID, bool status)
        {
            if (CheckIfBufferExist(parkingBufferID))
            {
                if (bufferList[parkingBufferID - 1].occupied != status)
                {
                    bufferList[parkingBufferID - 1].occupied = status;
                    return true;
                }
                else { return false; }
            }
            else
            {
                return false;
            }
        }
    }
    /// <summary>
    /// 缓冲位单元
    /// </summary>
    public class ParkingBuffer : ICloneable
    {
        /// <summary>
        /// 缓冲位ID
        /// </summary>
        public int bufferID;
        /// <summary>
        /// 占用标记
        /// </summary>
        public bool occupied;
        /// <summary>
        /// 单参数构造函数
        /// </summary>
        /// <param name="bufferID"></param>
        public ParkingBuffer(int bufferID)
            : this(bufferID, true)
        {
        }
        /// <summary>
        /// 双参数构造函数
        /// </summary>
        /// <param name="bufferID"></param>
        /// <param name="occupied"></param>
        public ParkingBuffer(int bufferID, bool occupied)
        {
            this.bufferID = bufferID;
            this.occupied = occupied;
        }

        public object Clone()
        {
            ParkingBuffer pbc = new ParkingBuffer(this.bufferID, this.occupied);
            return pbc;
        }
    }
}
