using AutoMapper;
using Kean.Domain.Wcs.Models;
using Kean.Infrastructure.Database;
using Kean.Infrastructure.Database.Repository.Default;
using Kean.Infrastructure.Database.Repository.Default.Entities;
using Kean.Infrastructure.Database.Repository.Default.Entities.Interface;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Kean.Infrastructure.Repository
{
    /// <summary>
    /// 控制仓库
    /// </summary>
    public class WcsRepository :
        Domain.Wcs.Repositories.IWcsRepository
    {
        private readonly IMapper _mapper; // 模型映射
        private readonly IDefaultDb _database; // 默认数据库

        /// <summary>
        /// 构造函数
        /// </summary>
        public WcsRepository(
            IMapper mapper,
            IDefaultDb database)
        {
            _mapper = mapper;
            _database = database;
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetInputs 方法
         */
        public async Task<IEnumerable<Input>> GetInputs()
        {
            return _mapper.Map<IEnumerable<Input>>(await _database.From<IO_CONTROL_APPLY>().Where(r=>r.APPLY_TASK_STATUS == 0).Select());
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.RemoveInput 方法
         */
        public async Task RemoveInput(int id)
        {
            await _database.From<IO_CONTROL_APPLY>()
                .Where(a => a.CONTROL_APPLY_ID == id)
                .Delete();
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.LogInput 方法
         */
        public async Task LogInput(Input input)
        {
            var entity = _mapper.Map<T_IO_CONTROL>(input);
            entity.UPDATE_TIME = entity.CREATE_TIME = DateTime.Now;
            await _database.From<T_IO_CONTROL>().Add(entity);
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetOutputs 方法
         */
        public async Task<IEnumerable<Output>> GetOutputs()
        {
            return _mapper.Map<IEnumerable<Output>>(await _database.From<IO_CONTROL>().Select());
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetOutput 方法
         */
        public async Task<Output> GetOutput(string barcode)
        {
            return _mapper.Map<Output>(await _database.From<IO_CONTROL>()
                .Where(c => c.STOCK_BARCODE == barcode)
                .Single());
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.HasOutput 方法
         */
        public async Task<bool> HasOutput(string barcode, string original, string destination)
        {
            var schema = _database.From<IO_CONTROL>();
            if (barcode != null)
            {
                schema.Where(c => c.STOCK_BARCODE == barcode);
            }
            if (original != null)
            {
                schema.Where(c => c.START_DEVICE_CODE == original);
            }
            if (destination != null)
            {
                schema.Where(c => c.END_DEVICE_CODE == destination);
            }
            return (await schema.Single(c => new { Count = Function.Count(c.CONTROL_ID) })).Count > 0;
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.CreateOutput 方法
         */
        public async Task<int> CreateOutput(Output model)
        {
            var entity = _mapper.Map<IO_CONTROL>(model);
            entity.END_WAREHOUSE_CODE = "SDLC";
            entity.START_WAREHOUSE_CODE = "SDLC";
            entity.PRE_CONTROL_STATUS = 0;
            entity.CONTROL_STATUS = 0;
            entity.ERROR_TEXT = string.Empty;
            entity.CONTROL_END_TIME = string.Empty;
            entity.CONTROL_REMARK = model.Data ?? string.Empty;
            if (model.Barcode.Substring(2, 1) == "F")
            {
                entity.GOODS_TYPE = "1";
            }
            else if (model.Barcode.Substring(2, 1) == "G")
            {
                entity.GOODS_TYPE = "2";
            }
            else
            {
                entity.GOODS_TYPE = "3";
            }
                
            return Convert.ToInt32(await _database.From<IO_CONTROL>().Add(entity));
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.SyncOutput 方法
         */
        public async Task SyncOutput(int id, int state)
        {
            await _database.From<IO_CONTROL>()
                .Where(c => c.CONTROL_ID == id)
                .Update(new { PRE_CONTROL_STATUS = state });
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.RemoveOutput 方法
         */
        public async Task RemoveOutput(int id)
        {
            await _database.From<IO_CONTROL>()
                .Where(c => c.CONTROL_ID == id)
                .Delete();
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.LogOutput 方法
         */
        public async Task LogOutput(Output model)
        {
            var entity = _mapper.Map<T_IO_CONTROL>(model);
            entity.UPDATE_TIME = entity.CREATE_TIME = DateTime.Now;
            await _database.From<T_IO_CONTROL>().Add(entity);
        }

        ////////////////////////////////////////////////////////
        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.RemoveOutputByTask 方法
         */
        public async Task RemoveOutputByTask(int task, string message)
        {
            var wcs = await _database.From<IO_CONTROL>()
                .Where(c => c.MANAGE_ID == task).Single();

            var entity = _mapper.Map<T_IO_CONTROL>(wcs);
            entity.CONTROL_PARAMETER = message;
            entity.UPDATE_TIME = entity.CREATE_TIME = DateTime.Now;
            await _database.From<T_IO_CONTROL>().Add(entity);

            await _database.From<IO_CONTROL>()
                .Where(c => c.MANAGE_ID == task)
                .Delete();
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetPassBackEndDevice 方法
         */
        public async Task<string> GetPassBackEndDevice(string device, string palletType)
        {
            var endDevices = await _database.From<IO_CONTROL_ROUTE>()
                .Where(r => r.CONTROL_ROUTE_TYPE == 5 && r.START_DEVICE == device)
                .Select();

            string backDevice = string.Empty;

            foreach (var backRoute in endDevices)
            {
                backDevice = backRoute.END_DEVICE;
                var backStation = await _database.From<T_WH_CELL>()
                    .Where(r => r.CELL_CODE == backRoute.END_DEVICE && r.CELL_TYPE == "Station")
                    .Single();
                if (backStation != null)
                {
                    backDevice = backStation.CELL_CODE;
                    break;
                }
            }

            return backDevice;
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.SetOutputStatus 方法
         */
        public async Task SetOutputStatus(int task, int status)
        {
            await _database.From<IO_CONTROL>()
                .Where(r => r.MANAGE_ID == task)
                .Update(new
                {
                    CONTROL_STATUS = status
                });
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetStationModels 方法
         */
        public async Task<IEnumerable<StationModel>> GetStationModels()
        {
            return _mapper.Map<IEnumerable<StationModel>>(await _database.From<IO_STATION_MODEL>()
                .Where(r=>r.IS_FULL != r.PRE_IS_FULL).Select());
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.SyncOutput 方法
         */
        public async Task SyncStationModel(string device, string isfull)
        {
            string updateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
            await _database.From<IO_STATION_MODEL>()
                .Where(r => r.STATION_CODE == device)
                .Update(new
                {
                    PRE_IS_FULL = isfull
                });

            var led = await _database.From<T_LED_MAIN>()
                .Where(r => r.DEVICE_CODE.Contains(device))
                .Single();

            //var station = await _database.From<IO_STATION_MODEL>()
            //    .Where(r=>r.STATION_CODE == device)
            //    .Single();

            ////入口 无货 发送
            //if (station.INOUT == "1" && isfull == "0")
            //{
            //}
            ////出口 无货 发送
            //if (station.INOUT == "2" && isfull == "0")
            //{
            //}

            if (led != null && isfull == "0")
            {
                await _database.From<T_LED_MAIN>()
                    .Where(r => r.LED_ID == led.LED_ID)
                    .Update(new
                    {
                        IS_SEND = "0",
                        UPDATE_TIME = updateTime
                    });

                await _database.From<T_LED_LIST>()
                   .Where(r => r.LED_ID == led.LED_ID && r.LINE_NO == "1")
                   .Update(new
                   {
                       LINE_TEXT = led.DEVICE_CODE.Substring(0,5) + "  空闲",
                       LED_LIST_REMARK = updateTime
                   });

                await _database.From<T_LED_LIST>()
                    .Where(r => r.LED_ID == led.LED_ID && r.LINE_NO == "2")
                    .Update(new
                    {
                        LINE_TEXT = " ",
                        LED_LIST_REMARK = updateTime
                    });
            }

        }


        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.LogOutput 方法  
         */
        public async Task LogOutput(StationModel model)
        {
            var entity = _mapper.Map<T_IO_CONTROL>(model);
            entity.UPDATE_TIME = entity.CREATE_TIME = DateTime.Now;
            await _database.From<T_IO_CONTROL>().Add(entity);
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.HasBypassStock 方法  
         */
        public async Task<bool> HasBypassStock(string barcode)
        {
            var stock = await _database.From<T_STORAGE_MAIN>()
                .Where(r => r.STOCK_BARCODE == barcode && r.TAG.Contains("BypassArea"))
                .Single(m => new { Count = Function.Count(m.STORAGE_ID) });

            return stock.Count > 0;
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.SetPriority 方法
         */
        public async Task SetPriority(int task, int priority)
        {
            await _database.From<IO_CONTROL>()
                .Where(r => r.MANAGE_ID == task)
                .Update(new
                {
                    CONTROL_TASK_LEVEL = priority.ToString()
                });
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.HasBypassEmpty 方法  
         */
        public async Task<bool> HasBypassEmpty(string barcode)
        {
            //var stock = await _database.From<V_STORAGE_LIST>()
            //    .Where(r => r.GOODS_CODE == barcode.Substring(3))
            //    .Single(m => new { Count = Function.Count(m.STORAGE_ID) });

            //return stock.Count > 0;

            var manage = await _database.From<V_MANAGE_MAIN>()
                .Where(r => (r.MANAGE_TYPE == "托盘出库" || r.MANAGE_TYPE == "输送")
                && r.STOCK_BARCODE.Contains(barcode.Substring(0,5))
                && r.END_AREA_NAME.Contains("一楼暂存区"))
                .Single(r => new { Count = Function.Count(r.MANAGE_ID) });

            return !(manage.Count > 0);
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetTaskByBarcode 方法
         */
        public async Task<Domain.Wcs.Models.WcsTask> GetTaskByBarcode(string barcode)
        {
            var task = await _database.From<T_MANAGE_MAIN>()
                .Where(m => m.STOCK_BARCODE == barcode)
                .Single();
            return task == null ? null : _mapper.Map< Domain.Wcs.Models.WcsTask> (task);
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetCellById 方法
         */
        public async Task<Domain.Wcs.Models.WcsCell> GetCellById(int id)
        {
            return _mapper.Map<Domain.Wcs.Models.WcsCell>(await _database.From<T_WH_CELL>()
                .Where(c => c.CELL_ID == id)
                .Single());
        }

        /*
         * 实现 Kean.Domain.Task.Repositories.ITaskRepository.GetPalletOutManageCountByType 方法
         */
        public async Task<int> GetPalletOutManageCountByType(string palletType)
        {
            string device = "12123";
            if (palletType == "W1JPA")
            {
                device = "22123";
            }

            var taskCount = await _database.From<T_MANAGE_MAIN>()
              .Where(r => r.END_CELL_ID == int.Parse(device))
              .Single(m => new { Count = Function.Count(m.MANAGE_ID) });
            return taskCount == null ? 0 : taskCount.Count;
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetPassGoEndDevice 方法
         */
        public async Task<string> GetPassGoEndDevice(string device)
        {
            var endDevice = await _database.From<IO_CONTROL_ROUTE>()
                .Where(r => r.CONTROL_ROUTE_TYPE == 4 && r.START_DEVICE == device)
                .Single();
            return endDevice?.END_DEVICE;
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.IsPallet 方法
         */
        public async Task<bool> IsPallet(string stockBarcode)
        {
            var storage = await _database.From<V_STORAGE_LIST>()
                .Where(r => r.STOCK_BARCODE == stockBarcode)
                .Single();

            var goods = await _database.From<T_GOODS_MAIN>().Where(r => r.GOODS_ID == storage.GOODS_ID).Single();

            return goods.TYPE_ID == "4";
        }

        public async Task<bool> HasInput(int task)
        {
            var schema = _database.From<IO_CONTROL>().Where(r => r.MANAGE_ID == task);

            return (await schema.Single(m => new { Count = Function.Count(m.CONTROL_ID) })).Count > 0;
        }


        /*
         * 初始化货位显示
         */
        public async Task InitCell()
        {
            int GAP = 2;
            int SHEN_sizeX = 21;
            int SHEN_sizeY = 28;

            int JIA_sizeX = 44;
            int JIA_sizeY = 10;

            int sizeX = 10;
            int sizeY = 10;
            int sizeZ = 10;

            var cells = await _database.From<T_WH_CELL>()
                .Where(r => r.CELL_TYPE == "Cell")
                .OrderBy(m => m.CELL_Z, Order.Ascending)
                .OrderBy(m => m.CELL_X, Order.Ascending)
                .OrderBy(m => m.CELL_Y, Order.Ascending)
                .Select();


            foreach (var m in cells)
            {
                int posX = 0;
                int posY = 0;
                int posZ = 0;

                //车架货位
                if (m.CELL_PALLET == "LCF")
                {
                    posX = (m.CELL_X.Value / 2 -1 ) * (JIA_sizeX + GAP);
                    posY = (m.CELL_Y.Value - 1) * (JIA_sizeY + GAP);

                    int laneCount = 0;
                    if (Convert.ToInt32(m.CELL_Z) % 2 == 1)
                    {
                        laneCount = Convert.ToInt32(m.CELL_LANEWAY) - 18000 - 1;
                    }
                    else
                    {
                        laneCount = Convert.ToInt32(m.CELL_LANEWAY) - 18000;
                    }

                    posZ = (m.CELL_Z.Value - 1 + laneCount) * (sizeZ + GAP);

                    var CELL_VISUAL = new
                    {
                        posX = posX,
                        posY = posY,
                        posZ = posZ,
                        sizeX = JIA_sizeX,
                        sizeY = JIA_sizeY,
                        sizeZ = sizeZ
                    };

                    await _database.From<T_WH_CELL>()
               .Where(c => c.CELL_ID == m.CELL_ID)
               .Update(new
               {
                   CELL_VISUAL = JsonConvert.SerializeObject(CELL_VISUAL)
               });
                }
                //车身货位
                if (m.CELL_PALLET == "LCG")
                {
                    posX = (m.CELL_X.Value - 2 ) * (SHEN_sizeX + GAP);
                    posY = (m.CELL_Y.Value - 4) * (SHEN_sizeY + GAP) + 3 * (JIA_sizeY + GAP);

                    int laneCount = 0;
                    if (Convert.ToInt32(m.CELL_Z) % 2 == 1)
                    {
                        laneCount = Convert.ToInt32(m.CELL_LANEWAY) - 18000 - 1;
                    }
                    else
                    {
                        laneCount = Convert.ToInt32(m.CELL_LANEWAY) - 18000;
                    }

                    posZ = (m.CELL_Z.Value - 1 + laneCount) * (sizeZ + GAP);

                    var CELL_VISUAL = new
                    {
                        posX = posX,
                        posY = posY,
                        posZ = posZ,
                        sizeX = SHEN_sizeX,
                        sizeY = SHEN_sizeY,
                        sizeZ = sizeZ
                    };

                    await _database.From<T_WH_CELL>()
               .Where(c => c.CELL_ID == m.CELL_ID)
               .Update(new
               {
                   CELL_VISUAL = JsonConvert.SerializeObject(CELL_VISUAL)
               });
                }

                //中大件货位
                if (m.CELL_PALLET == "LCA,LCB,LCC,LCD,LCE")
                {
                    posX = (m.CELL_X.Value - 2) * (sizeX + GAP);
                    posY = (m.CELL_Y.Value - 1) * (sizeY + GAP);

                    if (m.CELL_Z > 6)
                    {
                        posZ = (m.CELL_Z.Value - 5 + 1) * (sizeZ + GAP);
                    }
                    else
                    {
                        posZ = (m.CELL_Z.Value - 5) * (sizeZ + GAP);
                    }


                    var CELL_VISUAL = new
                    {
                        posX = posX,
                        posY = posY,
                        posZ = posZ,
                        sizeX = sizeX,
                        sizeY = sizeY,
                        sizeZ = sizeZ
                    };

                    await _database.From<T_WH_CELL>()
               .Where(c => c.CELL_ID == m.CELL_ID)
               .Update(new
               {
                   CELL_VISUAL = JsonConvert.SerializeObject(CELL_VISUAL)
               });
                }
            }


        }


        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.GetStockbarcode 方法
         */
        public async Task<string> GetStockbarcode(int station)
        {
            var stockBarcode = await _database.From<T_STORAGE_MAIN>()
                .Where(r => r.CELL_ID == station)
                .Single();
            return stockBarcode?.STOCK_BARCODE;
        }

        /*
         * 实现 Kean.Domain.Wcs.Repositories.IWcsRepository.CreateInputForShenAgvOut 方法
         */
        public async Task<int> CreateInputForShenAgvOut(Input model)
        {
            var entity = new IO_CONTROL_APPLY();
            entity.CONTROL_APPLY_TYPE = model.Function;
            entity.APPLY_TASK_STATUS = model.State;
            entity.DEVICE_CODE = model.Device;
            entity.CREATE_TIME = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            return Convert.ToInt32(await _database.From<IO_CONTROL_APPLY>().Add(entity));
        }
    }
}