using System;
using System.Collections.Generic;
using System.Linq;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Redis.RedisEntities;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.ToolRepository.Entities;
using Siger.Middlelayer.ToolRepository.Repositories.Interface;
using Siger.Middlelayer.ToolRepository.Response;
using System.Threading.Tasks;

namespace Siger.Middlelayer.ToolRepository.Repositories
{
    internal class SigerProjectToolSpindleTrueRepository : ApiToolRepositoryBase<SigerProjectToolSpindleTrue>,
        ISigerProjectToolSpindleTrueRepository
    {
        private readonly ApiToolDbContext context;
        public SigerProjectToolSpindleTrueRepository(ApiToolDbContext context) : base(context)
        {
            this.context = context;
        }
     
        public List<ToolCuterlocationInfo> getCutterLocationList(int projectId, int machineId, int spindleId, string programNo)
        {
            var result = new List<ToolCuterlocationInfo>();
            var program = from p in context.siger_project_tool_cutter_location_true
                where p.spindleid == spindleId && p.is_processing_program != (int)ProcessProgram.NoConfig && p.status == (int)RowState.Valid
                select p;
            
            var cfgList = program.ToList();
            foreach (var obj in cfgList)
            {
                // 刀位加工次数趋势线-只加载当前加工程序号的刀位信息 
                if (obj.is_processing_program==(int)ProcessProgram.MainProgram)
                {
                    if (obj.programno== programNo)
                    {
                        if (result.All(f => f.cutter_location_name != obj.name))
                        {
                            result.Add(new ToolCuterlocationInfo
                            {
                                cutter_location_id = obj.name.ToString(),
                                cutter_location_name = obj.name
                            });
                        }
                    }
                }else
                {
                    if (obj.subprogramno == programNo)
                    {
                        if (result.All(f => f.cutter_location_name != obj.name))
                        {
                            result.Add(new ToolCuterlocationInfo
                            {
                                cutter_location_id = obj.name.ToString(),
                                cutter_location_name = obj.name
                            });
                        }
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// 获取刀位
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="sectionId"></param>
        /// <returns></returns>
        public async Task<IEnumerable<SpindleCutterInfo>> GetMonitorData(int projectId, int sectionId)
        {
            return await Task.Run(() =>
             {
                 //  var mids = GetMachineIds(sectionId, projectId).ToList();
                 var sonlevel = GetSonLevelSectionIds(sectionId, projectId);
                 var query = from mid in sonlevel
                             join lsm in context.siger_project_level_section_machine on mid equals lsm.section_id
                             join m in context.siger_project_machine on lsm.machine_id equals m.id
                             join s in context.siger_project_tool_spindle_true on m.id equals s.equipid
                             join c in context.siger_project_tool_cutter_location_true on s.id equals c.spindleid
                             where m.projectid == projectId
                             && m.status == (int)RowState.Valid
                             && s.status == (int)RowState.Valid
                             && c.status == (int)RowState.Valid
                             && c.is_processing_program != (int)ProcessProgram.NoConfig
                             && c.ratedlife > 0
                             select new SpindleCutterInfo
                             {
                                 MachineId = m.id,
                                 MachineName = m.title,
                                 MachineCode = m.code,
                                 SpindleId = s.id,
                                 SpindleName = s.name,
                                 CutterName = c.name
                             };
                 var data = query.GroupBy(g => new { g.MachineId, g.MachineName, g.MachineCode, g.SpindleId, g.SpindleName, g.CutterName }).Select(s => new SpindleCutterInfo
                 {
                     MachineId = s.Key.MachineId,
                     MachineName = s.Key.MachineName,
                     MachineCode = s.Key.MachineCode,
                     SpindleId = s.Key.SpindleId,
                     SpindleName = s.Key.SpindleName,
                     CutterName = s.Key.CutterName
                 });

                 return data;
             });
        }

        public IEnumerable<ResponseMoniterInfo> GetMonitorData(int projectID,List<CNCEquipmentState>sates)
        {
            var query = from cnc in sates
                        join pm in context.siger_project_machine on cnc.MachineId equals pm.id
                        join plsm in context.siger_project_machine_attribution on pm.id equals plsm.machine
                        join spt in context.siger_project_tool_spindle_true on pm.id equals spt.equipid
                        join clt in context.siger_project_tool_cutter_location_true on spt.id equals clt.spindleid
                        join t in context.siger_project_tool on clt.toolid equals t.id into temp
                        from tools in temp.DefaultIfEmpty()
                        where pm.projectid == projectID
                         && pm.status == (int)RowState.Valid && plsm.status == (int)RowState.Valid &&
                         spt.status == (int)RowState.Valid && clt.status == (int)RowState.Valid &&
                         clt.is_processing_program != (int)ProcessProgram.NoConfig && clt.ratedlife > 0
                        && pm.category == (int)MachineCategory.NC
                        select new ResponseMoniterInfo
                        {
                            id=clt.id,
                            SectionID = plsm.station,
                            MachineID = pm.id,
                            MachineName = pm.title,
                            MachineCode = pm.code,
                            Spid = spt.id,
                            SpindleName = spt.name,
                            Toolid= clt.toolid,
                            ToolName = tools == null ? "Na" : tools.name,
                            Toollocation = clt.name,
                            DrawingCode = tools == null ? "Na" : tools.drawingcode,
                            IsProces = clt.is_processing_program,
                            Program = clt.programno,
                            SubProgram = clt.subprogramno,
                            TooLife = clt.ratedlife,
                            LastUpdate = cnc.LastUpdateTime,
                            Desc=clt.description,
                            cncProgram=cnc.PN,
                            cncSubProgram=cnc.SPN
                        };
            return query.OrderBy(o => o.MachineID);
        }
       
        public List<SectionMachine> GetMachine(int projectId, int sectionId)
        {
            var machines= GetMachineIds(sectionId, projectId);
            var result = new List<SectionMachine>();
            foreach (var m in machines)
            {
                var code = context.siger_project_machine.FirstOrDefault(f => f.projectid == projectId && f.id==m && f.status==(int)RowState.Valid);
                if (code!=null)
                {
                    result.Add(new SectionMachine {
                        MachineId = m,
                        MachineCode = code.code,
                        MachineTitle=code.title,
                        Status=code.status
                    });
                }
               
            }
            return result;
        }

        public int GetMachineIdBySectionId(int sectionId, int projectId)
        {
            var query = from s in context.siger_project_level_section_machine
                join m in context.siger_project_machine on s.machine_id equals m.id
                where s.section_id == sectionId && s.status == (int) RowState.Valid && m.status == (int) RowState.Valid
                      && m.projectid == projectId && m.category == (int)MachineCategory.NC
                select s;
            if (!query.Any())
            {
                return 0;
            }
            return query.First().machine_id;
        }

        /// <summary>
        /// 检查设备当前运行的程序号是否为加工程序号
        /// </summary>
        /// <param name="machineId"></param>
        /// <param name="spindleId"></param>
        /// <param name="pn"></param>
        /// <param name="spn"></param>
        /// <returns></returns>
        public SigerProjectToolCutterLocationTrue CheckProcessProgramBySpindle(int machineId,int spindleId, string pn ,string spn)
        {
            var cutterLocaltion = from p in context.siger_project_tool_cutter_location_true
                where p.spindleid == spindleId && p.ratedlife > 0 && ((p.programno == pn && p.is_processing_program == (int)ProcessProgram.MainProgram ||
                                                    p.subprogramno == spn && p.is_processing_program == (int)ProcessProgram.ChildProgram)) 
                                               && p.status == (int)RowState.Valid
                select p;
            return cutterLocaltion.FirstOrDefault();
        }

        public ResponseSpindleList GetSpindleListBySection(int machineId, int projectId)
        {
            var result = new ResponseSpindleList
            {
                spindle_list = new List<Spindlelist>()
            };
            var spindlequery = from p in context.siger_project_tool_spindle_true
                               join t in context.siger_project_tool_cutter_location_true on  p.id equals t.spindleid
                join m in context.siger_project_machine on p.equipid equals m.id
                where p.equipid == machineId && p.status == (int) RowState.Valid && m.status == (int) RowState.Valid
                      && m.projectid == projectId && t.is_processing_program !=(int)ProcessProgram.NoConfig && m.category == (int)MachineCategory.NC
                select new Spindlelist
                {
                    machine_id = m.id,
                    machine_name = m.title,
                    spindle_name = p.name,
                    spindle_id = p.id
                };

            if (spindlequery.Any())
            {
                foreach (var s in spindlequery.ToList())
                {
                    if(!result.spindle_list.Exists(f=>f.spindle_id==s.spindle_id))
                    {
                        result.spindle_list.Add(s);
                    }
                }
                result.spindle_list=result.spindle_list.OrderBy(o => o.spindle_name).ToList();
                result.machine_name = result.spindle_list.First().machine_name;
            }
            return result;
        }

        /// <summary>
        /// 获取1分钟以内的报警信息
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="machineId"></param>
        /// <returns></returns>
        public IEnumerable<SigerProjectToolCutterLocationAlarm> GetProjectToolCutterLocationAlarms(int projectId, int machineId)
        {
            try
            {
                var beforeOneMin = UnixTimeHelper.ConvertDataTimeLong(DateTime.Now.AddMinutes(-1));
                var cutterAlarm = from p in context.siger_project_tool_cutter_location_alarm
                                  where p.project_id == projectId && p.machine_id == machineId && p.alarm_time > beforeOneMin && p.status == (int)RowState.Valid
                                  select p;
                var CutterLocationAlarms = cutterAlarm.Where(f => true);
                return CutterLocationAlarms;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
       
        /// <summary>
        /// 监控历史 获取主轴下所有的加工程序号
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="machineId"></param>
        /// <param name="Spindle"></param>
        /// <returns></returns>
        public IEnumerable<ResponseProgramlist> GetProcessProgramlist(int projectId, int machineId, int Spindle)
        {
            var cutterLocationList = from tcl in context.siger_project_tool_cutter_location_true
                                   join ts in context.siger_project_tool_spindle_true on tcl.spindleid equals ts.id
                                   join m in context.siger_project_machine on ts.equipid equals m.id
                                   where m.id == machineId && ts.name == Spindle.ToString() && tcl.ratedlife > 0 && tcl.status == (int)RowState.Valid &&
                                   ts.status == (int)RowState.Valid && m.status == (int)RowState.Valid && tcl.is_processing_program != (int)ProcessProgram.NoConfig
                                         && m.category == (int)MachineCategory.NC
                                   select new ResponseToolLifeList
                                   {
                                       id=tcl.id,
                                       programno=tcl.programno,
                                       subprogramno=tcl.subprogramno,
                                       IsProcess=tcl.is_processing_program,
                                       machineId=m.id
                                   };

            var result = new List<ResponseProgramlist>();
            foreach (var obj in cutterLocationList)
            {
                if (obj.IsProcess == (int)ProcessProgram.MainProgram)
                {
                    if (string.IsNullOrEmpty(obj.programno))
                        continue;
                    if (!result.Exists(f => f.programno == obj.programno))
                        result.Add(new ResponseProgramlist { machineid = obj.machineId.ToString(), programno = obj.programno });
                }
                else
                {
                    if (string.IsNullOrEmpty(obj.subprogramno))
                        continue;
                    if (!result.Exists(f => f.programno == obj.subprogramno))
                        result.Add(new ResponseProgramlist { machineid = obj.machineId.ToString(), programno = obj.subprogramno });
                }
            }
            return result.Distinct();
        }

        public IEnumerable<ResponseMoniterInfo> GetToolifeData(int projectID, List<CNCEquipmentState> sates)
        {
            var query = from cnc in sates
                        join pm in context.siger_project_machine on cnc.MachineId equals pm.id
                        join plsm in context.siger_project_level_section_machine on pm.id equals plsm.machine_id
                        join spt in context.siger_project_tool_spindle_true on pm.id equals spt.equipid
                        join clt in context.siger_project_tool_cutter_location_true on spt.id equals clt.spindleid

                        where pm.projectid == projectID &&
                        pm.status == (int)RowState.Valid && plsm.status == (int)RowState.Valid &&
                        spt.status == (int)RowState.Valid && clt.status == (int)RowState.Valid &&
                        clt.name != "0" &&
                        cnc.PN==clt.programno && cnc.SPN== clt.subprogramno && pm.category == (int)MachineCategory.NC
                        select new ResponseMoniterInfo
                        {
                            id = clt.id,
                            SectionID = plsm.section_id,
                            MachineID = pm.id,
                            MachineName = pm.title,
                            MachineCode = pm.code,
                            Spid = spt.id,
                            SpindleName = spt.name,
                            Toolid = clt.toolid,
                            //  ToolName = tools == null ? "Na" : tools.name,
                            Toollocation = clt.name,
                            //   DrawingCode = tools == null?"Na": tools.drawingcode,
                            IsProces = clt.is_processing_program,
                            Program = clt.programno,
                            SubProgram = clt.subprogramno,
                            TooLife = clt.ratedlife,
                            LastUpdate = cnc.LastUpdateTime,
                            Desc = clt.description,
                            cncProgram = cnc.PN,
                            cncSubProgram = cnc.SPN
                        };
            return query.OrderBy(o => o.MachineID);
        }

        public List<ResponseMachineSpindle> getMachineSpindels(int machineId)
        {
            return context.siger_project_tool_spindle_true.Where(f => f.status == (int)RowState.Valid && f.equipid == machineId).
                Select(f=>new ResponseMachineSpindle
                {
                    id=f.id,
                    name=f.name
                }).ToList();
        }
    }
}