using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.ToolRepository.Entities;
using Siger.Middlelayer.ToolRepository.Repositories.Interface;
using Siger.Middlelayer.ToolRepository.Response;
using ResponseToolAlarmStatisticsInfo = Siger.Middlelayer.Repository.Data.ResponseToolAlarmStatisticsInfo;

namespace Siger.Middlelayer.ToolRepository.Repositories
{
    internal class SigerProjectToolcutterLocationalarmRepository :
        ApiToolRepositoryBase<SigerProjectToolCutterLocationAlarm>, ISigerProjectToolcutterLocationalarmRepository
    {
        ApiToolDbContext context;
        public SigerProjectToolcutterLocationalarmRepository(ApiToolDbContext context) : base(context)
        {
            this.context = context;
        }

        public List<ResponseGetToolAlarmLogInfo> GetAlarmList(int sectionId, int projectId, out int totalCount, string timeSpan, int page, int pageSize)
        {
            var machineIdList = GetMachineIds(sectionId, projectId);
            var toolCutterLocation = context.siger_project_tool_cutter_location_alarm.Where
                                 (f => f.status == RowState.Valid.GetHashCode());
            var r = from a in toolCutterLocation
                    join m in context.siger_project_machine
                    on a.machine_id equals m.id into temp
                    from abc in temp.DefaultIfEmpty()
                    where abc.status == RowState.Valid.GetHashCode()
                    && machineIdList.Contains(abc.id)
                    select new ResponseGetToolAlarmLogInfo
                    {
                        machine_name = abc.title,
                        machine_id = abc.id,
                        machine_code = abc.code,
                        spindle_name = a.spindle_name,
                        cutter_location_name = a.cutter_location_name,
                        program_no = a.program_no,
                        alarm_time = UnixTimeHelper.ConvertStringDateTime(a.alarm_time.ToString()).ToString("yyyy-MM-dd hh:mm:ss"),
                        alarmtime = a.alarm_time,
                        error_msg = a.error_msg,
                        alarm_grade = a.alarm_grade
                    };
            Expression<Func<ResponseGetToolAlarmLogInfo, bool>> startExpression = q => true;
            Expression<Func<ResponseGetToolAlarmLogInfo, bool>> endExpression = q => true;
            if (!string.IsNullOrEmpty(timeSpan))
            {
                var timeArr = timeSpan.Split(new string[] { " - " }, StringSplitOptions.RemoveEmptyEntries);
                if (timeArr.Count() == 1)
                {
                    DateTime.TryParse(timeArr[0], out DateTime startTime);
                    startExpression = f => f.alarmtime >= UnixTimeHelper.ConvertDataTimeLong(startTime);
                }
                if (timeArr.Count() == 2)
                {
                    DateTime.TryParse(timeArr[0], out DateTime startTime);
                    DateTime.TryParse(timeArr[1], out DateTime endTime);
                    startExpression = f => f.alarmtime >= UnixTimeHelper.ConvertDataTimeLong(startTime);
                    endExpression = f => f.alarmtime <= UnixTimeHelper.ConvertDataTimeLong(endTime);
                }
            }
            var predicate = startExpression.And(endExpression);
            totalCount = r.Count(predicate);
            var listResult = r.Where(predicate).Skip((page - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
            return listResult;
        }

        public IEnumerable<ResponseGetToolAlarmLogInfo> ExportAlarmList(int sectionId, int projectId, string timeSpan)
        {
            var machineIdList = GetMachineIds(sectionId, projectId);
            if (!machineIdList.Any())
            {
                return new List<ResponseGetToolAlarmLogInfo>();
            }
            var toolCutterLocation = context.siger_project_tool_cutter_location_alarm.Where(f => f.status == (int)RowState.Valid && f.project_id == projectId);
            var r = from a in toolCutterLocation
                    join m in context.siger_project_machine
                    on a.machine_id equals m.id into temp
                    from abc in temp.DefaultIfEmpty()
                    where abc.status == RowState.Valid.GetHashCode()
                    && machineIdList.Contains(abc.id)
                    select new ResponseGetToolAlarmLogInfo
                    {
                        machine_name = abc.title,
                        machine_id = abc.id,
                        machine_code = abc.code,
                        spindle_name = a.spindle_name,
                        cutter_location_name = a.cutter_location_name,
                        program_no = a.program_no,
                        alarmtime = a.alarm_time,
                        error_msg = a.error_msg,
                        alarm_grade = a.alarm_grade
                    };
            Expression<Func<ResponseGetToolAlarmLogInfo, bool>> startExpression = q => true;
            Expression<Func<ResponseGetToolAlarmLogInfo, bool>> endExpression = q => true;
            if (!string.IsNullOrEmpty(timeSpan))
            {
                var timeArr = timeSpan.Split(new string[] { " - " }, StringSplitOptions.RemoveEmptyEntries);
                if (timeArr.Length == 1)
                {
                    DateTime.TryParse(timeArr[0], out var startTime);
                    startExpression = f => f.alarmtime >= UnixTimeHelper.ConvertDataTimeLong(startTime);
                }
                if (timeArr.Length == 2)
                {
                    DateTime.TryParse(timeArr[0], out var startTime);
                    DateTime.TryParse(timeArr[1], out var endTime);
                    startExpression = f => f.alarmtime >= UnixTimeHelper.ConvertDataTimeLong(startTime);
                    endExpression = f => f.alarmtime <= UnixTimeHelper.ConvertDataTimeLong(endTime);
                }
            }
            var predicate = startExpression.And(endExpression);
            return r.Where(predicate).AsNoTracking().ToList();
        }

        /// <summary>
        /// 报警统计
        /// </summary>
        /// <param name="sectionId"></param>
        /// <param name="projectId"></param>
        /// <param name="timeSpan"></param>
        /// <param name="alarmData"></param>
        /// <returns></returns>
        public AlarmStatistFinalResult GetToolAlarmStatisticsInfo(int sectionId, int projectId, string timeSpan, List<ToolAlarmStatisticsInfo> alarmData)
        {
            var machineIdList = GetMachineIds(sectionId, projectId);
            //var toolCutterLocation = context.siger_project_tool_cutter_location_alarm.Where
            //                     (f => f.status == RowState.Valid.GetHashCode());
            DateTime startTime = DateTime.Now.Date;
            DateTime endTime = (DateTime.Now.Date.AddDays(1)).AddSeconds(-1);//23:59:59
            if (!string.IsNullOrEmpty(timeSpan))
            {
                var timeArr = timeSpan.Split(new string[] { " - " }, StringSplitOptions.RemoveEmptyEntries);
                if (timeArr.Count() == 1)
                {
                    DateTime.TryParse(timeArr[0], out startTime);
                }
                if (timeArr.Count() == 2)
                {
                    DateTime.TryParse(timeArr[0], out startTime);
                    DateTime.TryParse(timeArr[1], out endTime);
                }
            }
            var data = new List<AlarmStatistAll>();
            //循环遍历时间，计算每天的报警情况
            for (DateTime i = startTime; i < endTime;)
            {
                var tmpEnd = (i.AddDays(1)).AddSeconds(-1);//23:59:59
                var tmp = GetToolAlarmStatisticsInfo(projectId, machineIdList, i.Date, tmpEnd, alarmData);
                data.Add(new AlarmStatistAll
                {
                    time = i.ToString("yyyy-MM-dd"),
                    data = tmp
                });
                i = i.AddDays(1);
            }
            if (data.Count == 0)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var arr1 = new AlarmStatistResult();
            foreach (var item in data)
            {
                arr1.datetime.Add(item.time);
                foreach (var i in item.data)
                {
                    switch ((AlarmGrade)i.alarm_grade)
                    {
                        case AlarmGrade.Quality:
                            arr1.zl.Add(i.value);
                            break;
                        case AlarmGrade.ToolDieLine:
                            arr1.sm.Add(i.value);
                            break;
                        case AlarmGrade.Wear:
                            arr1.ms.Add(i.value);
                            break;
                        case AlarmGrade.Broken:
                            arr1.bz.Add(i.value);
                            break;
                        case AlarmGrade.Destroyed:
                            arr1.dd.Add(i.value);
                            break;
                        default:
                            break;
                    }
                }
            }
            //总的数据
            var res = GetToolAlarmStatisticsInfo(projectId, machineIdList, startTime, endTime, alarmData);
            if (res.Count == 0)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var arr2 = new AlarmStatistNameResult2();
            foreach (var item in res)
            {
                arr2.name.Add(item.name);
                switch ((AlarmGrade)item.alarm_grade)
                {
                    case AlarmGrade.Quality:
                        arr2.zl += item.value;
                        break;
                    case AlarmGrade.ToolDieLine:
                        arr2.sm += item.value;
                        break;
                    case AlarmGrade.Wear:
                        arr2.ms += item.value;
                        break;
                    case AlarmGrade.Broken:
                        arr2.bz += item.value;
                        break;
                    case AlarmGrade.Destroyed:
                        arr2.dd += item.value;
                        break;
                    default:
                        break;
                }
            }
            return new AlarmStatistFinalResult() { data1 = arr1, data2 = arr2 };
        }

        private List<ResponseToolAlarmStatisticsInfo> GetToolAlarmStatisticsInfo(int projectId, IEnumerable<int> machineIdList, DateTime startTime, DateTime tmpEnd, List<ToolAlarmStatisticsInfo> alarmList)
        {
            var stime = UnixTimeHelper.ConvertDataTimeLong(startTime);
            var etime = UnixTimeHelper.ConvertDataTimeLong(tmpEnd);
            alarmList = alarmList.Where(f => f.alarmtime > stime && f.alarmtime < etime).ToList();
            var arr = new List<ResponseToolAlarmStatisticsInfo>();

            arr.Add(
                new ResponseToolAlarmStatisticsInfo() { name = EnumHelper.GetEnumDesc(ToolEnum.Quality), alarm_grade = (int)AlarmGrade.Quality }//, color = "#008080" }
                );
            arr.Add(
            new ResponseToolAlarmStatisticsInfo() { name = EnumHelper.GetEnumDesc(ToolEnum.ToolDieLine), alarm_grade = (int)AlarmGrade.ToolDieLine }//, color = "#FF975A" }
                );
            arr.Add(
                new ResponseToolAlarmStatisticsInfo() { name = EnumHelper.GetEnumDesc(ToolEnum.Wear), alarm_grade = (int)AlarmGrade.Wear }//, color = "#4B96F5" }
                );
            arr.Add(
                new ResponseToolAlarmStatisticsInfo() { name = EnumHelper.GetEnumDesc(ToolEnum.Broken), alarm_grade = (int)AlarmGrade.Broken }//, color = "#E66400" }
                );
            arr.Add(
                new ResponseToolAlarmStatisticsInfo() { name = EnumHelper.GetEnumDesc(ToolEnum.Destroyed), alarm_grade = (int)AlarmGrade.Destroyed }//, color = "#00FF00" }
                );
            if (alarmList != null && alarmList.Count != 0)
            {
                foreach (var item in alarmList)
                {
                    foreach (var i in arr)
                    {
                        if (item.alarm_grade != 0 && item.alarm_grade == i.alarm_grade)
                        {
                            i.value += item.count;
                        }
                    }
                }
            }
            arr.Sort();
            return arr;
        }

        public List<ProgramNo> GetProgralList(ProgramConfig config, int sectionId, int projectId, string name, int count)
        {
            var result = new List<ProgramNo>();
            Expression<Func<ProgramConfigInfo, bool>> FunProgram = f => true;

            if (config == ProgramConfig.NotConfig)
            {
                FunProgram = q => q.isProcess == (int)ProcessProgram.NoConfig;
            }
            else
            {
                FunProgram = q => q.isProcess != (int)ProcessProgram.NoConfig;
            }
            Expression<Func<ProgramConfigInfo, bool>> FunProgramNo = f => true;
            if (!string.IsNullOrEmpty(name))
            {
                FunProgramNo = q => q.Program.Contains(name);
            }

            var mids = GetMachineIds(sectionId, projectId);
            var tmp = from tcl in context.siger_project_tool_cutter_location_true.Distinct()
                      join ts in context.siger_project_tool_spindle_true on tcl.spindleid equals ts.id
                      where mids.Contains(ts.equipid) &&
                       ts.status == (int)RowState.Valid && tcl.status == (int)RowState.Valid
                      select new ProgramConfigInfo
                      {
                          isProcess = tcl.is_processing_program,
                          Program = tcl.programno,
                          SubProgram = tcl.subprogramno
                      };
            var predicates = FunProgram.And(FunProgramNo);
            var programs = tmp.Where(predicates).AsNoTracking().ToList();


            foreach (var p in programs)
            {
                if (p.isProcess == (int)ProcessProgram.NoConfig)
                {

                    if (!string.IsNullOrEmpty(p.SubProgram) && !result.Exists(f => f.programno == p.SubProgram))
                        result.Add(new ProgramNo(p.SubProgram));
                    if (!string.IsNullOrEmpty(p.Program) && !result.Exists(f => f.programno == p.Program))
                        result.Add(new ProgramNo(p.Program));
                }
                else if (p.isProcess == (int)ProcessProgram.MainProgram)
                {
                    if (result.Exists(f => f.programno == p.Program))
                        continue;
                    if (!string.IsNullOrEmpty(p.Program))
                        result.Add(new ProgramNo(p.Program));
                }
                else if (p.isProcess == (int)ProcessProgram.ChildProgram)
                {
                    if (result.Exists(f => f.programno == p.SubProgram))
                        continue;
                    if (!string.IsNullOrEmpty(p.SubProgram))
                        result.Add(new ProgramNo(p.SubProgram));
                }
            }
            if (count == 0)
            {
                return result.OrderBy(q => q.programno).ToList();
            }
            else
            {
                return result.OrderBy(q => q.programno).Take(count).ToList();
            }
        }

        public List<ResponseToolConfigInfo> GetToolConfigInfo(string programNo, int sectionID, int projectID, int page, int pagesize, out int totalCount)
        {

            var mids = GetMachineIds(sectionID, projectID);

            Expression<Func<ResponseToolConfigInfo, bool>> FunProgram = f => true;
            var query = 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
                        join tl in context.siger_project_tool on tcl.toolid equals tl.id into ttemp
                        from tool in ttemp.DefaultIfEmpty()
                        join pd in context.siger_project_product on tcl.productid equals pd.id into ptemp
                        from product in ptemp.DefaultIfEmpty()
                        where mids.Contains(m.id) &&
                        tcl.status == (int)RowState.Valid && ts.status == (int)RowState.Valid && m.status == (int)RowState.Valid &&
                        tcl.is_processing_program != (int)ProcessProgram.NoConfig &&
                        tcl.ratedlife > 0
                        orderby tcl.is_identical_collection, tcl.programno, tcl.subprogramno, tcl.update_time descending
                        select new ResponseToolConfigInfo
                        {
                            id = tcl.id,
                            ratedlife = tcl.ratedlife.ToString(),
                            machine_id = m.id,
                            machine_name = m.title,
                            machine_code = m.code,
                            spindle_name = ts.name,
                            tool_name = tool == null ? "Na" : tool.name,
                            tool_id = tool == null ? "0" : tool.id.ToString(),
                            drawingcode = tool == null ? "Na" : tool.drawingcode,
                            product_id = product == null ? "Na" : product.id.ToString(),
                            product_name = product == null ? "Na" : product.name,
                            productdrawingcode = product == null ? "Na" : product.drawingcode,
                            product_code = product == null ? "Na" : product.code,
                            cutter_location_name = tcl.name,
                            is_identical_collection = tcl.is_identical_collection,
                            cutter_location_alias = tcl.cutter_location_alias,
                            programno = tcl.is_processing_program == (int)ProcessProgram.MainProgram ? tcl.programno : tcl.subprogramno,
                            subprogramno = tcl.subprogramno,
                            isProcessValue = tcl.is_processing_program,
                            is_processing_program = tcl.is_processing_program == (int)ProcessProgram.MainProgram ?
                            EnumHelper.GetEnumDesc(ProcessProgram.MainProgram) : EnumHelper.GetEnumDesc(ProcessProgram.ChildProgram),
                            type = tcl.type,
                            coefficent = tcl.coefficent
                        };
            if (!string.IsNullOrEmpty(programNo))
            {
                FunProgram = f => f.programno.Contains(programNo);
            }
            // totalCount = query.Where(FunProgram).Count();
            totalCount = query.Where(FunProgram).Count();
            var datasource = query.Where(FunProgram).OrderBy(o => o.machine_id).ThenBy(o => o.spindle_name).ThenBy(o => o.tool_name).ThenBy(o => o.programno).ToList().Select((x, i) => new ResponseToolConfigInfo
            {
                id = x.id,
                numbers = i + 1,
                ratedlife = x.ratedlife,
                machine_id = x.machine_id,
                machine_name = x.machine_name,
                machine_code = x.machine_code,
                spindle_name = x.spindle_name,
                tool_name = x.tool_name,
                tool_id = x.tool_id,
                drawingcode = x.drawingcode,
                product_id = x.product_id,
                product_name = x.product_name,
                productdrawingcode = x.productdrawingcode,
                product_code = x.product_code,
                cutter_location_name = x.cutter_location_name,
                is_identical_collection = x.is_identical_collection,
                cutter_location_alias = x.cutter_location_alias,
                programno = x.programno,
                subprogramno = x.subprogramno,
                isProcessValue = x.isProcessValue,
                is_processing_program = x.is_processing_program,
                type = x.type,
                coefficent = x.coefficent
            }).ToList();

            var result = datasource.Skip((page - 1) * pagesize).Take(pagesize).ToList();
            return result;
        }
        #region remove 
        //public List<ResponseToolConfigInfo> GetToolConfigInfo(string programNo, int sectionID, int projectID, int page, int pagesize, out int totalCount)
        //{
        //    var mids = GetMachineIds(sectionID, projectID);
        //    var tootal = (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 into tmp1
        //                  from t1 in tmp1.DefaultIfEmpty()
        //                  join m in context.siger_project_machine
        //                  on t1.equipid equals m.id into tmp2
        //                  from t2 in tmp2.DefaultIfEmpty()
        //                  where mids.Contains(t2.id) && tcl.status == (int)RowState.Valid && t1.status == (int)RowState.Valid &&
        //                  t2.status == (int)RowState.Valid && tcl.is_processing_program != (int)ProcessProgram.NoConfig && tcl.ratedlife > 0
        //                  orderby tcl.is_identical_collection, tcl.programno, tcl.subprogramno, tcl.update_time descending
        //                  select new ResponseToolConfigInfo
        //                  {
        //                      id = tcl.id,
        //                      ratedlife = tcl.ratedlife.ToString(),
        //                      machine_id = t2.id,
        //                      machine_name = t2.title,
        //                      machine_code = t2.code,
        //                      spindle_name = t1.name,
        //                      cutter_location_name = tcl.name,
        //                      is_identical_collection = tcl.is_identical_collection,
        //                      cutter_location_alias = tcl.cutter_location_alias,
        //                      programno = tcl.programno,
        //                      subprogramno = tcl.subprogramno,
        //                      isProcessValue=tcl.is_processing_program,
        //                      //is_processing_program = tcl.is_processing_program.ToString(),
        //                      // is_processing_program= tcl.is_processing_program==0? EnumHelper.GetEnumDesc(CommonEnum.No): EnumHelper.GetEnumDesc(CommonEnum.Yes)
        //                      is_processing_program = tcl.is_processing_program.ToString() ,
        //                      type=tcl.type
        //                  });
        //    if (!string.IsNullOrEmpty(programNo))
        //    {
        //        tootal = tootal.Where(f => f.programno == programNo);
        //    }
        //    totalCount = tootal.ToList().Count;
        //    if (totalCount == 0)
        //    {
        //        return new List<ResponseToolConfigInfo>();
        //    }
        //    var data = tootal.Skip((page - 1) * pagesize).Take(pagesize).ToList();
        //    if (data.Count == 0)
        //    {
        //        return new List<ResponseToolConfigInfo>();
        //    }
        //    var number = (page - 1) * pagesize + 1;
        //    for (int i = 0; i < data.Count; i++)
        //    {
        //        data[i].numbers = i + number;
        //        var tmp = (from tcl in context.siger_project_tool_cutter_location_true
        //                   join t in context.siger_project_tool
        //                   on tcl.toolid equals t.id into tmp1
        //                   from t1 in tmp1.DefaultIfEmpty()
        //                   join p in context.siger_project_product
        //                   on tcl.productid equals p.id into tmp2
        //                   from t2 in tmp2.DefaultIfEmpty()
        //                   where tcl.id == data[i].id && tcl.status == (int)RowState.Valid &&
        //                   t1.status == (int)RowState.Valid && t2.status == (int)RowState.Valid
        //                   select new //ToolConfigInfo
        //                   {
        //                       tcl.ratedlife,
        //                       tool_id = t1.id,
        //                       tool_name = t1.name,
        //                       t1.spec,
        //                       t1.drawingcode,
        //                       product_id = t2.id,
        //                       product_name = t2.name,
        //                       product_code = t2.code,
        //                       tcl.programno,
        //                       tcl.subprogramno,
        //                       tcl.is_processing_program
        //                   }).ToList().FirstOrDefault();
        //        if (tmp != null)
        //        {
        //            data[i].ratedlife = tmp.ratedlife.ToString() ?? "";
        //            data[i].tool_id = tmp.tool_id.ToString() ?? "";
        //            data[i].tool_name = tmp.tool_name;
        //            data[i].spec = tmp.spec;
        //            data[i].drawingcode = tmp.drawingcode;
        //            data[i].product_id = tmp.product_id.ToString() ?? "";
        //            data[i].product_name = System.Web.HttpUtility.HtmlDecode(tmp.product_name);
        //            data[i].product_code = tmp.product_code;
        //            if (string.IsNullOrWhiteSpace(tmp.subprogramno))
        //            {
        //                data[i].programno = tmp.programno;
        //                //data[i].is_processing_program = tmp.is_processing_program == (int) ProcessProgram.MainProgram
        //                //    ? EnumHelper.GetEnumDesc(CommonEnum.Yes)
        //                //    : EnumHelper.GetEnumDesc(CommonEnum.No);
        //            }
        //            else
        //            {
        //                data[i].programno = tmp.is_processing_program == (int) ProcessProgram.MainProgram
        //                    ? tmp.programno
        //                    : tmp.subprogramno;
        //                data[i].is_processing_program = EnumHelper.GetEnumDesc(CommonEnum.Yes);
        //            }
        //        }
        //        else
        //        {
        //            //data[i].ratedlife = "";
        //            //data[i].tool_id = "";
        //            //data[i].tool_name = "";
        //            //data[i].spec = "";
        //            data[i].drawingcode = "";
        //            //data[i].product_id = "";
        //            //data[i].product_name = "";
        //            //data[i].product_code = "";
        //            //data[i].programno = "";
        //            // data[i].is_processing_program = "";
        //        }
        //        data[i].is_processing_program = data[i].is_processing_program == "0" ? EnumHelper.GetEnumDesc(CommonEnum.No) : EnumHelper.GetEnumDesc(CommonEnum.Yes);
        //    }

        //    return data;
        //}

        #endregion
        public List<ResponseOriginalToolConfigInfo> GetOriginalToolConfigInfo(string programNo, string spn, int sectionId, int projectId, int page, int pagesize, out int totalCount)
        {
            var tootal = from tcl in context.siger_project_tool_cutter_location_true
                         join t1 in context.siger_project_tool_spindle_true on tcl.spindleid equals t1.id
                         join t2 in context.siger_project_machine on t1.equipid equals t2.id
                         where t2.id == sectionId && tcl.status == (int)RowState.Valid && t1.status == (int)RowState.Valid && t2.status == (int)RowState.Valid
                         && tcl.is_processing_program == (int)ProcessProgram.NoConfig
                         && tcl.programno == programNo && tcl.subprogramno == spn && t2.category == (int)MachineCategory.NC
                         orderby tcl.update_time descending
                         select new ResponseOriginalToolConfigInfo
                         {
                             id = tcl.id,
                             cutter_location_name = tcl.name,
                             programno = string.IsNullOrWhiteSpace(tcl.programno)
                                 ? tcl.subprogramno
                                 : (!string.IsNullOrWhiteSpace(tcl.subprogramno) ? tcl.programno + "," + tcl.subprogramno : tcl.programno),
                             MainProgramNo = tcl.programno,
                             SubProgramNo = tcl.subprogramno,
                             machine_id = t2.id,
                             spindle_name = t1.name,
                             machine_name = t2.title,
                             machine_code = t2.code
                         };
            if (!string.IsNullOrWhiteSpace(programNo))
            {
                tootal = tootal.Where(f => f.MainProgramNo == programNo || f.SubProgramNo == programNo);
            }
            totalCount = tootal.Count();
            var tmp = tootal.OrderBy(o => o.machine_id).OrderBy(o => o.spindle_name).OrderBy(o => o.cutter_location_name).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            var number = (page - 1) * pagesize;
            for (int i = 1; i <= tmp.Count; i++)
            {
                tmp[i - 1].numbers = i + number;
            }
            return tmp;
        }

        public ResponseGetCutterLocationEditInfo GetCutterLocationEditInfo(int id)
        {
            var tootal = 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
                         join t in context.siger_project_tool on tcl.toolid equals t.id into temp1
                         from tb1 in temp1.DefaultIfEmpty()
                         join p in context.siger_project_product on tcl.productid equals p.id into temp2
                         from tb2 in temp2.DefaultIfEmpty()
                         where tcl.id == id && tcl.status == (int)RowState.Valid && ts.status == (int)RowState.Valid &&
                               m.status == (int)RowState.Valid && m.category == (int)MachineCategory.NC
                         select new ResponseGetCutterLocationEditInfo
                         {
                             ratedlife = tcl.ratedlife.Value,
                             cutter_location_name = tcl.name,
                             programno = tcl.programno,
                             subprogramno = tcl.subprogramno,
                             spindle_name = ts.name,
                             machine_id = m.id,
                             machine_name = m.title,
                             machine_code = m.code,
                             cutter_location_alias = tcl.cutter_location_alias,
                             is_processing_program = tcl.is_processing_program,
                             tool_id = tb1 != null ? tb1.id : 0,
                             tool_name = tb1 != null ? tb1.name : "",
                             drawingcode = tb1 != null ? tb1.drawingcode : "",
                             product_id = tb2 != null ? tb2.id : 0,
                             product_code = tb2 != null ? tb2.code : "",
                             product_drawingcode = tb2 != null ? tb2.drawingcode : "",
                             product_name = tb2 != null ? tb2.name : "",
                             coefficent = tcl.coefficent
                         };

            return tootal.FirstOrDefault();
        }
        /// <summary>
        /// v1.5新增获取未配置刀具信息页面列表
        /// </summary>
        /// <param name="program_no"></param>
        /// <param name="sectionid"></param>
        /// <param name="projectId"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalCount"></param>
        /// <returns></returns>
        public IEnumerable<ResponseUnConfigProgramList> GetUnConfigProgramList(string program_no, int sectionid, int projectId, int page, int pageSize, out int totalCount)
        {
            var mids = GetMachineIds(sectionid, projectId);
            var total = 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 into tmp1
                        from t1 in tmp1.DefaultIfEmpty()
                        join m in context.siger_project_machine on t1.equipid equals m.id into tmp2
                        from t2 in tmp2.DefaultIfEmpty()
                        where mids.Contains(t2.id) && tcl.status == (int)RowState.Valid && t1.status == (int)RowState.Valid &&
                              t2.status == (int)RowState.Valid && tcl.is_processing_program == (int)ProcessProgram.NoConfig
                        orderby tcl.update_time descending
                        select new ResponseUnConfigProgramList
                        {
                            machine_id = t2.id,
                            programno = tcl.programno,
                            subprogramno = tcl.subprogramno,
                            machine_name = t2.title,
                            machine_code = t2.code,
                            is_processing_program = tcl.is_processing_program,
                        };
            if (!string.IsNullOrWhiteSpace(program_no))
            {
                total = total.Where(f => f.programno == program_no || f.subprogramno == program_no);
            }
            total = total.Distinct();
            totalCount = total.Count();
            var tmp = total.Skip((page - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
            return tmp;
        }
        public IEnumerable<ResponseConfigProgramlist> GetConfigProgramList(string program_no, int sectionid, int projectId, int page, int pageSize, out int totalCount)
        {
            var mids = GetMachineIds(sectionid, projectId);
            Expression<Func<CfgToolsInfo, bool>> FunProgram = f => true;
            //配置程序号分组
            var total = 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 mids.Contains(m.id) && tcl.status == (int)RowState.Valid && ts.status == (int)RowState.Valid &&
                              m.status == (int)RowState.Valid && tcl.is_processing_program != (int)ProcessProgram.NoConfig
                        orderby tcl.update_time descending
                        select new CfgToolsInfo
                        {
                            machine_id = m.id,
                            programno = tcl.is_processing_program == (int)ProcessProgram.MainProgram ? tcl.programno : tcl.subprogramno,
                            machine_name = m.title,
                            machine_code = m.code,
                            is_processing_program = tcl.is_processing_program
                        };
            if (!string.IsNullOrEmpty(program_no))
            {
                FunProgram = f => f.programno == program_no;
            }
            var groupCfg = total.Where(FunProgram).GroupBy(x => new { x.machine_id, x.machine_name, x.machine_code, x.programno, x.is_processing_program }).Select(s => new ResponseConfigProgramlist
            {
                machine_id = s.Key.machine_id,
                machine_name = s.Key.machine_name,
                machine_code = s.Key.machine_code,
                programno = s.Key.programno,
                is_processing_program = s.Key.is_processing_program
            });
            totalCount = groupCfg.Count();
            var machinePn = groupCfg.Skip((page - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
            return machinePn;
        }

        public IEnumerable<SpindleSorting> GetToolinfosByPn(int machine, string program, int is_process)
        {
            Expression<Func<CycleToolinfo, bool>> FunProgram = f => true;
            var total = 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
                        where ts.equipid == machine
                        select new CycleToolinfo
                        {
                            Spinde = int.Parse(ts.name),
                            Toolno = int.Parse(tcl.name),
                            Pn = tcl.programno,
                            Spn = tcl.subprogramno
                        };

            if (!string.IsNullOrEmpty(program))
            {
                if (is_process == (int)ProcessProgram.MainProgram)
                    FunProgram = f => f.Pn == program;
                else
                    FunProgram = f => f.Spn == program;
            }
            var data = total.Where(FunProgram).ToList();

            var result = new List<SpindleSorting>();
            if (data.Any())
            {
                var gpSpindle = data.GroupBy(g => g.Spinde);
                foreach (var g in gpSpindle)
                {
                    var spid = g.Key;
                    var tlst = g.ToList().Select(f => f.Toolno).Distinct().ToList();
                    result.Add(new SpindleSorting
                    {
                        no = spid,
                        tools = tlst
                    });
                }
            }
            return result;

        }

        public IEnumerable<ResponseToolCCModeConfigInfo> GetToolCCModeConfigInfos(string programNo, int sectionID, int projectID, int page, int pagesize, out int totalCount)
        {
            var mids = GetMachineIds(sectionID, projectID);

            Expression<Func<ResponseToolCCModeConfigInfo, bool>> FunProgram = f => true;
            var query = 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 mids.Contains(m.id) && tcl.status == (int)RowState.Valid && ts.status == (int)RowState.Valid && m.status == (int)RowState.Valid &&
                        tcl.is_processing_program != (int)ProcessProgram.NoConfig &&
                        tcl.ratedlife > 0
                        select new ResponseToolCCModeConfigInfo
                        {
                            id = tcl.id,
                            machine_id = m.id,
                            machine_name = m.title,
                            machine_code = m.code,
                            spindle_name = ts.name,
                            cutter_location_name = tcl.name,
                            programno = tcl.is_processing_program == (int)ProcessProgram.MainProgram ? tcl.programno : tcl.subprogramno,

                            is_processing_program = tcl.is_processing_program == (int)ProcessProgram.MainProgram ?
                            EnumHelper.GetEnumDesc(ProcessProgram.MainProgram) : EnumHelper.GetEnumDesc(ProcessProgram.ChildProgram),
                        };
            if (!string.IsNullOrEmpty(programNo))
            {
                FunProgram = f => f.programno.Contains(programNo);
            }
            totalCount = query.Where(FunProgram).Count();
            var result = query.Where(FunProgram).Skip((page - 1) * pagesize).Take(pagesize).ToList();
            return result;
        }
    }
}