using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Newtonsoft.Json;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Redis.Repositories;
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.Request;
using Siger.Middlelayer.ToolRepository.Response;

namespace Siger.Middlelayer.ToolRepository.Repositories
{
    internal class SigerProjectToolblxRepository : ApiToolRepositoryBase<SigerProjectToolBlx>,
        ISigerProjectToolblxRepository
    {
        ApiToolDbContext apiToolDbContext;
        public SigerProjectToolblxRepository(ApiToolDbContext context) : base(context)
        {
            apiToolDbContext = context;
        }
        public List<ToolStudyList> GetToolStudyList(int sectionID,string programNo, int projectID, int page, int pagesize, out int totalCount)
        {
            //const int AUTO_STUDY = 1;

            var mids = GetMachineIds(sectionID, projectID);

            Expression<Func<ToolStudyList, bool>> Funcat = f => true;
            var query = from m in apiToolDbContext.siger_project_machine
                        join sp in apiToolDbContext.siger_project_tool_spindle_true on m.id equals sp.equipid
                        join tl in apiToolDbContext.siger_project_tool_cutter_location_true on sp.id equals tl.spindleid
                        join blx in apiToolDbContext.siger_project_tool_blx on m.id equals blx.machine_id
                        where m.projectid == projectID && m.status == (int)RowState.Valid && sp.status == (int)RowState.Valid && tl.status == (int)RowState.Valid
                        && mids.Contains(m.id) && tl.is_processing_program != (int)ProcessProgram.NoConfig 
                        && blx.project_id==m.projectid && blx.machine_id==m.id && blx.spindle_name==sp.name && blx.program_no==(tl.is_processing_program==(int)ProcessProgram.MainProgram?tl.programno:tl.subprogramno)
                        select new ToolStudyList
                        {
         
                            machine_id = m.id,
                            machine_code = m.code,
                            machine_name = m.title,
                            spindle_name = sp.name,
                            start_time= UnixTimeHelper.ConvertIntDateTime(blx.start_time),
                            end_time= UnixTimeHelper.ConvertIntDateTime(blx.end_time),
                            auto_study=tl.auto_study==1?1:0,
                            program_no = blx.program_no,
                            spindle_id=sp.id

                        };

            if (!string.IsNullOrEmpty(programNo))
            {
                Funcat = f => f.program_no.Contains(programNo);
            }

            var groupData= query.Where(Funcat).GroupBy(x => new { x.machine_id, x.machine_name, x.machine_code, x.spindle_name, x.program_no,x.start_time,x.end_time,x.auto_study }).Select(g => new ToolStudyList
            {
                machine_id = g.Key.machine_id,
                machine_name = g.Key.machine_name,
                machine_code = g.Key.machine_code,
                spindle_name = g.Key.spindle_name,
                program_no = g.Key.program_no,
                start_time=g.Key.start_time,
                end_time=g.Key.end_time,
                auto_study=g.Key.auto_study

            }).ToList();

            totalCount = groupData.Count();

            return groupData.OrderBy(o=>o.machine_id).ThenBy(o=>o.spindle_name).Skip((page - 1) * pagesize).Take(pagesize).ToList();

            //var mids = GetMachineIds(sectionID, projectID);

            //Expression<Func<ToolStudyList, bool>> Funkey = f => true;
            //var data = from tb in apiToolDbContext.siger_project_tool_blx
            //           join m in apiToolDbContext.siger_project_machine
            //           on tb.machine_id equals m.id into tmp1
            //           from t1 in tmp1.DefaultIfEmpty()
            //           join ts in apiToolDbContext.siger_project_tool_spindle_true
            //           on new { equipid = tb.machine_id, name = tb.spindle_name } equals new { ts.equipid, ts.name }
            //           into ret
            //           from r in ret.DefaultIfEmpty()
            //           where mids.Contains(t1.id) && tb.status == (int)RowState.Valid &&
            //                r.status == (int)RowState.Valid && t1.status == (int)RowState.Valid
            //           orderby tb.machine_id, tb.spindle_name
            //           select new ToolStudyList
            //           {
            //               id = tb.id,
            //               spindle_id = r.id,//??0,
            //               spindle_name = tb.spindle_name,
            //               program_no = tb.program_no,
            //               start_time = UnixTimeHelper.ConvertIntDateTime(tb.start_time),
            //               end_time = UnixTimeHelper.ConvertIntDateTime(tb.end_time),
            //               machine_id = t1.id,//??0,
            //               machine_name = t1.title ?? "",
            //               machine_code = t1.code ?? ""
            //           };
            ////on m.// into tb1

            //if (!string.IsNullOrEmpty(programNo))
            //{
            //    Funkey = f => f.program_no.Contains(programNo);
            //}
            //totalCount = data.Where(Funkey).Count();

            //var result = data.Where(Funkey).Skip((page - 1) * pagesize).Take(pagesize).ToList();
            //foreach (var item in result)
            //{
            //    //查询是否自动学习开关
            //    var x = (from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
            //             join tst in apiToolDbContext.siger_project_tool_spindle_true
            //             on tcl.spindleid equals tst.id into tmp1
            //             from r in tmp1.DefaultIfEmpty()
            //             where r.id == item.spindle_id && tcl.programno == item.program_no && tcl.status == (int)RowState.Valid &&
            //                      r.status == (int)RowState.Valid
            //             select tcl.auto_study).FirstOrDefault();
            //    item.auto_study = x ?? AUTO_STUDY;
            //}

            //return result;
        }

        public List<ToolUnStudyList> GetToolUnStudyList(int sectionID,string programNo, int projectID, int page, int pagesize, out int totalCount)
        {
            var mids = GetMachineIds(sectionID, projectID);
            var tbs = apiToolDbContext.siger_project_tool_blx.Where(f=>f.project_id==projectID && mids.Contains(f.machine_id)).ToList();
            Expression<Func<ToolUnStudyList, bool>> Funcat = f => true;
            var query = from m in apiToolDbContext.siger_project_machine
                        join sp in apiToolDbContext.siger_project_tool_spindle_true on m.id equals sp.equipid
                        join tl in apiToolDbContext.siger_project_tool_cutter_location_true on sp.id equals tl.spindleid
                        //join blx in apiToolDbContext.siger_project_tool_blx on m.id equals blx.machine_id
                        where m.projectid == projectID && m.status == (int)RowState.Valid && sp.status == (int)RowState.Valid && tl.status == (int)RowState.Valid
                        && mids.Contains(m.id) && tl.is_processing_program != (int)ProcessProgram.NoConfig
                        && !tbs.Exists(f=>f.project_id==m.projectid && f.machine_id==m.id && f.spindle_name==sp.name && f.program_no==(tl.is_processing_program == (int)ProcessProgram.MainProgram ? tl.programno : tl.subprogramno))
                        select new ToolUnStudyList
                        {

                            machine_id = m.id,
                            machine_code = m.code,
                            machine_name = m.title,
                            spindle_name = sp.name,
                            auto_study = tl.auto_study == 1 ? 1 : 0,
                            programno=tl.is_processing_program==(int)ProcessProgram.MainProgram?tl.programno:tl.subprogramno

                        };

            if (!string.IsNullOrEmpty(programNo))
            {
                Funcat = f => f.programno.Contains(programNo);
            }

            var groupData = query.Where(Funcat).GroupBy(x => new { x.machine_id, x.machine_name, x.machine_code, x.spindle_name, x.programno, x.auto_study }).Select(g => new ToolUnStudyList
            {
                machine_id = g.Key.machine_id,
                machine_name = g.Key.machine_name,
                machine_code = g.Key.machine_code,
                spindle_name = g.Key.spindle_name,
                programno=g.Key.programno,
                auto_study = g.Key.auto_study

            }).ToList();

            totalCount = groupData.Count();

            return groupData.OrderBy(o => o.machine_id).ThenBy(o => o.spindle_name).Skip((page - 1) * pagesize).Take(pagesize).ToList();
            //var mids = GetMachineIds(sectionID, projectID);
            //var tbs = apiToolDbContext.siger_project_tool_blx.ToList();

            //Expression<Func<ToolUnStudyList, bool>> Funkey = f => true;
            //Expression<Func<ToolUnStudyList, bool>> FunNotNull = f => !string.IsNullOrEmpty(f.programno);

            //var dataQuery = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
            //           join tst in apiToolDbContext.siger_project_tool_spindle_true
            //           on tcl.spindleid equals tst.id into tmp1
            //           from t1 in tmp1.DefaultIfEmpty()
            //           join m in apiToolDbContext.siger_project_machine
            //           on t1.equipid equals m.id into tmp3
            //           from r in tmp3.DefaultIfEmpty()
            //           where
            //                tbs.Where(f => f.machine_id == t1.equipid && f.spindle_name == t1.name && f.program_no == tcl.programno).Count() == 0 &&
            //                mids.Contains(r.id) && tcl.is_processing_program != (int)ProcessProgram.NoConfig && tcl.ratedlife > 0 &&
            //                tcl.status == (int)RowState.Valid && t1.status == (int)RowState.Valid && r.status == (int)RowState.Valid
            //           //orderby new { t2.equipid, t2.name }
            //           select new ToolUnStudyList
            //           {
            //               programno = (tcl.is_processing_program == (int)ProcessProgram.MainProgram) ? tcl.programno : tcl.subprogramno,
            //               auto_study = tcl.auto_study,
            //               id = t1.id,
            //               spindle_name = t1.name,
            //               machine_id = r.id,
            //               machine_name = r.title,
            //               machine_code = r.code
            //           };
            //if (!string.IsNullOrEmpty(programNo))
            //{
            //    Funkey = f => f.programno.Contains(programNo);
            //}
            //var predicate = Funkey.And(FunNotNull);

            //var tmp = dataQuery.Where(predicate).OrderBy(f => f.programno).ThenBy(f => f.spindle_name).ThenBy(f => f.machine_id).ToList();
            ////tmp=tmp.Distinct<ToolUnStudyList>().ToList();
            //tmp = tmp.GroupBy(f => new { f.programno, f.spindle_name, f.machine_id }).Select(f =>
            //  new ToolUnStudyList
            //  {
            //      programno = f.FirstOrDefault().programno,//已在select中调整,此处直接使用
            //      auto_study = f.FirstOrDefault().auto_study,
            //      id = f.FirstOrDefault().id,
            //      spindle_name = f.FirstOrDefault().spindle_name,
            //      machine_id = f.FirstOrDefault().machine_id,
            //      machine_name = f.FirstOrDefault().machine_name,
            //      machine_code = f.FirstOrDefault().machine_code
            //  }).ToList();
            ////tmp = tmp.Distinct().ToList();
            //totalCount = tmp.Count();

            //var list = tmp.Skip((page - 1) * pagesize).Take(pagesize).ToList();

            //return list;
        }

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

            var cfgMachine = GetLineMachineConfig(projectID, sectionID, programNo);

            var blx = apiToolDbContext.siger_project_tool_blx_cutter.Where(f=>f.project_id==projectID).ToList();
            var querydata = from cfg in cfgMachine
                            where !blx.Exists(f =>f.project_id==cfg.ProjectId && f.machine_id == cfg.MachineId && f.spindle_name == cfg.SpinldeName && f.cutter_location_name == cfg.CuterLocateName &&f.program_no==cfg.Program)
                            select new OutLineUnStudyList
                            {
                                 machine_id=cfg.MachineId,
                                 machine_code=cfg.MachineCode,
                                 machine_name=cfg.MachineTile,
                                 spindle_name=cfg.SpinldeName,
                                 cutter_location_name=cfg.CuterLocateName,
                                 programno=cfg.Program
                            };
            totalCount = querydata.Count();
            return querydata.OrderBy(o=>o.machine_id).ThenBy(o=>o.spindle_name).Skip((page - 1) * pagesize).Take(pagesize).ToList();

            //var mids = GetMachineIds(sectionID, projectID);
            //var cb = apiToolDbContext.siger_project_tool_blx_cutter.ToList();
            //Expression<Func<OutLineUnStudyList, bool>> Funkey = f => true;
            //Expression<Func<OutLineUnStudyList, bool>> FunNotNull = f =>!string.IsNullOrEmpty(f.programno);
            //var query = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
            //           join tst in apiToolDbContext.siger_project_tool_spindle_true
            //           on tcl.spindleid equals tst.id into tmp1
            //           from t1 in tmp1.DefaultIfEmpty()
            //           join m in apiToolDbContext.siger_project_machine
            //           on t1.equipid equals m.id into tmp3
            //           from r in tmp3.DefaultIfEmpty()
            //           where
            //                cb.Where(f => f.machine_id == t1.equipid && f.spindle_name == t1.name && f.cutter_location_name == tcl.name && f.program_no == tcl.programno).Count() == 0 &&
            //                mids.Contains(r.id) && tcl.is_processing_program != (int)ProcessProgram.NoConfig &&

            //                tcl.status == (int)RowState.Valid && t1.status == (int)RowState.Valid && r.status == (int)RowState.Valid
            //           //orderby new { t2.equipid, t2.name }
            //           select new OutLineUnStudyList
            //           {
            //               programno = (tcl.is_processing_program == (int)ProcessProgram.MainProgram) ? tcl.programno : tcl.subprogramno,
            //               cutter_location_name = tcl.name,
            //               id = tcl.id,
            //               spindle_name = t1.name,
            //               machine_id = r.id,
            //               machine_name = r.title,
            //               machine_code = r.code
            //           };

            //if (!string.IsNullOrEmpty(programNo))
            //{
            //    Funkey = f => f.programno.Contains(programNo);
            //}
            //var predicate =Funkey.And(FunNotNull);

            //var tmp = query.Where(predicate).OrderBy(f => f.programno).ThenBy(f => f.spindle_name).ThenBy(f => f.machine_id).ToList();

            //tmp = tmp.GroupBy(f => new { f.cutter_location_name, f.programno, f.spindle_name, f.machine_id }).Select(f =>
            //   new OutLineUnStudyList
            //   {
            //       programno = f.FirstOrDefault().programno,//已在select中调整,此处直接使用
            //       cutter_location_name = f.FirstOrDefault().cutter_location_name,
            //       id = f.FirstOrDefault().id,
            //       spindle_name = f.FirstOrDefault().spindle_name,
            //       machine_id = f.FirstOrDefault().machine_id,
            //       machine_name = f.FirstOrDefault().machine_name,
            //       machine_code = f.FirstOrDefault().machine_code
            //   }).ToList();
            //totalCount = tmp.Count();
            //var list = tmp.Skip((page - 1) * pagesize).Take(pagesize).ToList();

            //return list;
        }

        public void EnvelopingLineStudy(string RService, ProgramListRepository repository, int userID, int companyId, int projectId,int machineId,int spindleId, int blxID, long startTime, long endTime, string programNo,int desc)
        {
            //var blxInfo = apiToolDbContext.siger_project_tool_blx.FirstOrDefault(f => f.id == blxID && f.status == (int)RowState.Valid);
            //if (blxInfo == null)
            //{
            //    throw new BadRequestException(CommonEnum.RecordNotFound);
            //}
            //var spindleName = blxInfo.spindle_name;
            //var machineId = blxInfo.machine_id;
            ComputeBlx(0, RService, repository, companyId, projectId, startTime, endTime, machineId, spindleId, programNo, userID,0,0,desc);
        }

        public void EnvelopingLineUnStudy(string RService, ProgramListRepository repository, int userId, int companyId, int projectId, int machineId,int spindle_id, long starttime, long endtime, string programno,int desc)
        {
            //var spindleInfo = apiToolDbContext.siger_project_tool_spindle_true.FirstOrDefault(f => f.id == spindle_id && f.status == (int)RowState.Valid);
            //if (spindleInfo == null)
            //{
            //    throw new BadRequestException(CommonEnum.RecordNotFound);
            //}
            //var spindleName = spindleInfo.name;
            //var machineId = spindleInfo.equipid;
            ComputeBlx(0, RService, repository, companyId, projectId, starttime, endtime, machineId, spindle_id, programno, userId,0,0,desc);
        }
        /// <summary>
        /// 极值轮廓线 已经学习 编辑
        /// </summary>
        /// <param name="RService"></param>
        /// <param name="repository"></param>
        /// <param name="userId"></param>
        /// <param name="companyId"></param>
        /// <param name="projectId"></param>
        /// <param name="blx_id"></param>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        /// <param name="machineId"></param>
        /// <param name="spindleName"></param>
        /// <param name="cutterLocationName"></param>
        /// <param name="programno"></param>
        /// <param name="cutter_type"></param>
        /// <param name="num"></param>
        /// <param name="desc"></param>
        /// <param name="remark"></param>
        public void EnvelopingOutlineStudy(string RService, ProgramListRepository repository, int userId, int companyId, int projectId, int blx_id,
            long starttime, long endtime, int machineId, int spindleName, int cutterLocationName, string programno, ToolMarkType cutter_type, int num, int desc, string remark = "")
        {
            ComputeBlx(num, RService, repository, companyId, projectId, starttime, endtime, machineId, spindleName, programno, userId, cutter_type, cutterLocationName,desc,remark);
        }
        /// <summary>
        /// 极值轮廓线 未学习 -保存
        /// </summary>
        /// <param name="RService"></param>
        /// <param name="repository"></param>
        /// <param name="userId"></param>
        /// <param name="companyId"></param>
        /// <param name="projectId"></param>
        /// <param name="spindle_id"></param>
        /// <param name="cutter_location_id"></param>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        /// <param name="machineId"></param>
        /// <param name="spindleName"></param>
        /// <param name="cutterLocationName"></param>
        /// <param name="programno"></param>
        /// <param name="cutter_type"></param>
        /// <param name="count"></param>
        /// <param name="desc"></param>
        /// <param name="remark"></param>
        public void EnvelopingOutlineUnStudy(string RService, ProgramListRepository repository, int userId, int companyId, int projectId, int spindle_id,
            int cutter_location_id, long starttime, long endtime, int machineId, int spindleName, int cutterLocationName, string programno, ToolMarkType cutter_type, int count,int desc,string remark="")
        {

            ComputeBlx(count, RService, repository, companyId, projectId, starttime, endtime, machineId, spindleName, programno, userId, cutter_type, cutterLocationName,desc,remark);
        }
        /// <summary>
        /// 判断程序号是否在指定时间段内出现,并调用数据分析提供的接口
        /// </summary>
        /// <param name="count"></param>
        /// <param name="RService"></param>
        /// <param name="repository"></param>
        /// <param name="companyId"></param>
        /// <param name="projectId"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="machineId"></param>
        /// <param name="spindle"></param>
        /// <param name="programNo"></param>
        /// <param name="userID"></param>
        /// <param name="cutter_type"></param>
        /// <param name="cutterLocationName"></param>
        /// <param name="desc"></param>
        /// <param name="remark"></param>
        private void ComputeBlx(int count, string RService, ProgramListRepository repository, int companyId, int projectId, long startTime, long endTime, int machineId,
                                int spindle, string programNo, int userID, ToolMarkType cutter_type, int cutterLocationName,int desc,string remark="")
        {
            //tool v1.5移除
            //13位时间戳
            RequestComputeBlx parameter;
            if (cutter_type == ToolMarkType.NotMarkType)
            {
                parameter = new RequestComputeBlx()
                {
                    companyID = companyId,
                    projectID = projectId,
                    spindleID = spindle,
                    machineID = machineId,
                    ccStart = startTime,
                    ccEnd = endTime,
                    programNum = programNo
                };
            }
            else
            {
                //极值轮廓线  -检查交集
                if (GetTimeIntersection(projectId, machineId, spindle.ToString(), cutterLocationName.ToString(), programNo, startTime, endTime, (int)cutter_type))
                {
                    throw new BadRequestException(ToolEnum.ExitsTypeMark);
                }

                parameter = new RequestComputeBlxWithCutterType
                {
                    companyID = companyId,
                    projectID = projectId,
                    spindleID = spindle,
                    machineID = machineId,
                    ccStart = startTime,
                    ccEnd = endTime,
                    programNum = programNo,
                    side = (int)cutter_type,
                    toolNum = cutterLocationName,
                    ccNum = count,
                    label = cutter_type.ToString()

                };
            }
      

            var senddata = JsonConvert.SerializeObject(parameter);
            //极值轮廓线
            var url = cutter_type == ToolMarkType.NotMarkType ? CommonConst.ComputeBlx : CommonConst.OutLine;

            var retData = HttpClientHelper.HttpPost(RService + url, senddata);
            HttpPostResult postResult;
            try
            {
                postResult = ((HttpPostResult)JsonConvert.DeserializeObject(retData, typeof(HttpPostResult)));
            }
            catch (Exception)
            {

                throw new Exception("jsonconvert error:" + retData);
            }
            if (postResult.ret != ((int)CommonEnum.Succefull))
            {
                switch (postResult.ret)
                {
                    case 0:
                        throw new BadRequestException(ToolEnum.BLXUpdateFalse);
                    case 44:
                        throw new BadRequestException(ToolEnum.NoData);
                    case 45:
                        throw new BadRequestException(ToolEnum.NoWorkPiece);
                    case 49:
                        throw new BadRequestException(ToolEnum.ErrorPullHBase);

                    case 43:
                        throw new BadRequestException(ToolEnum.CanNotConnectToMongoDB);
                    case 46:
                        throw new BadRequestException(ToolEnum.NoData);
                    case 47:
                        throw new BadRequestException(CommonEnum.RecordNotFound);
                    case 51:
                        throw new BadRequestException(ToolEnum.NotTranining);
                    case 61:
                        throw new BadRequestException(ToolEnum.ErrorStepNumber);
                    case 62:
                        throw new BadRequestException(ToolEnum.NoSignal);
                }
                throw new BadRequestException(ToolEnum.Error);
            }
            else
            {
                if (cutter_type == ToolMarkType.NotMarkType)
                {
                    //写入包络线表
                    SaveBlx(companyId, projectId, startTime, endTime, machineId, spindle.ToString(), programNo, userID);
                }
                else
                {
                    //写入轮廓线表
                    SaveCutter(companyId, projectId, startTime, endTime, machineId, spindle.ToString(), programNo, userID, cutterLocationName.ToString(), (int)cutter_type, count,desc,remark);
                }
                //更新主轴是否已学习字段
                var spindleData = apiToolDbContext.siger_project_tool_spindle_true.Where(f => f.equipid == machineId && f.name == spindle.ToString() && f.status == (int)RowState.Valid).FirstOrDefault();
                if (spindleData != null)
                {
                    spindleData.isstudy = ((int)ISStudy.ISStudy).ToString();
                    apiToolDbContext.siger_project_tool_spindle_true.Update(spindleData);
                }
                if (apiToolDbContext.SaveChanges() <= 0)
                {
                    throw new BadRequestException(CommonEnum.SystemExcetion);
                }
            }
        }

        /// <summary>
        /// 写入轮廓线表
        /// </summary>
        /// <param name="companyId"></param>
        /// <param name="projectId"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="machineId"></param>
        /// <param name="spindleName"></param>
        /// <param name="programNo"></param>
        /// <param name="userID"></param>
        /// <param name="cutterLocationName"></param>
        /// <param name="type"></param>
        /// <param name="count"></param>
        ///  <param name="desc"></param>
        /// <param name="remark"></param>
        private void SaveCutter(int companyId, int projectId, long startTime, long endTime, int machineId, string spindleName, string programNo, int userID, string cutterLocationName, int type, int count,int desc,string remark)
        {
            //var blxDetail = apiToolDbContext.siger_project_tool_blx_cutter.Where(f => f.machine_id == machineId && f.spindle_name == spindleName &&
            //                                                                  f.cutter_location_name == cutterLocationName && f.program_no == programNo && f.status == (int)RowState.Valid).FirstOrDefault();

        

            var blxDetail = apiToolDbContext.siger_project_tool_blx_cutter.Where(f => f.machine_id == machineId &&
            f.spindle_name == spindleName && f.cutter_location_name == cutterLocationName && f.program_no == programNo && f.type==type && f.status == (int)RowState.Valid).FirstOrDefault();

            if (blxDetail != null)
            {

                blxDetail.userid = userID;//标定人
                blxDetail.type = type;
                blxDetail.count = count;

                blxDetail.start_time = (int)startTime;
                blxDetail.end_time = (int)endTime;
                blxDetail.update_time = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now);
                blxDetail.qualitydesc = desc;
                blxDetail.remark = remark;
                apiToolDbContext.siger_project_tool_blx_cutter.Update(blxDetail);
            }
            else
            {
                var newData = new SigerProjectToolBlxCutter
                {
                    userid = userID,//标定人
                    type = type,
                    company_id = companyId,
                    project_id = projectId,
                    machine_id = machineId,
                    spindle_name = spindleName,
                    cutter_location_name = cutterLocationName,
                    program_no = programNo,
                    count=count,
                    start_time = (int)startTime,
                    end_time = (int)endTime,
                    create_time = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now),
                    update_time = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now),
                    status = (int)RowState.Valid,
                    qualitydesc=desc,
                    remark=remark
                };
                apiToolDbContext.siger_project_tool_blx_cutter.Add(newData);
            }
            ////记录日志
            //var logData = new SigerProjectToolBlxCutterLog
            //{
            //    machine_id = machineId,
            //    spindle_name = spindleName,
            //    cutter_location_name = cutterLocationName,
            //    program_no = programNo,
            //    start_time = (int)startTime,
            //    end_time = (int)endTime,
            //    study_user = userID.ToString(),
            //    create_time = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now)
            //};
            //apiToolDbContext.siger_project_tool_blx_cutter_log.Add(logData);
        }

        /// <summary>
        ///  极值-检查时间交集 
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="machine"></param>
        /// <param name="spindle"></param>
        /// <param name="toolno"></param>
        /// <param name="program"></param>
        /// <param name="type"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        private bool GetTimeIntersection(int projectId, int machine,string  spindle,string toolno,string program ,long startTime, long endTime,int type)
        {
            bool result = false;
            Expression<Func<SigerProjectToolBlxCutter, bool>> FunStime = f =>f.start_time >=startTime && f.start_time <= endTime;
            Expression<Func<SigerProjectToolBlxCutter, bool>> FunEtime = f => f.end_time >= startTime && f.end_time <= endTime;
            var query = from b in apiToolDbContext.siger_project_tool_blx_cutter
                        where b.project_id == projectId && b.machine_id == machine && 
                        b.spindle_name == spindle && b.cutter_location_name == toolno  && b.program_no == program &&
                        b.type!=type
                      
                        select new SigerProjectToolBlxCutter
                        {
                             project_id=b.project_id,
                             machine_id=b.machine_id,
                             spindle_name=b.spindle_name,
                             cutter_location_name=b.cutter_location_name,
                             program_no=b.program_no,
                             start_time=b.start_time,
                             end_time=b.end_time,
                             update_time=b.update_time,
                             type=b.type
                        };
            var predicate = FunStime.Or(FunEtime);
            var record = query.Where(predicate).Count();
            if (record>0)
            {
                return true;
            }
            return result;
        }
        /// <summary>
        /// //写入包络线表
        /// </summary>
        /// <param name="companyId"></param>
        /// <param name="projectId"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="machineId"></param>
        /// <param name="spindleName"></param>
        /// <param name="programNo"></param>
        /// <param name="userID"></param>
        private void SaveBlx(int companyId, int projectId, long startTime, long endTime, int machineId, string spindleName, string programNo, int userID)
        {
            var blxDetail = apiToolDbContext.siger_project_tool_blx.FirstOrDefault(f => f.machine_id == machineId && f.spindle_name == spindleName &&
                                                                              f.program_no == programNo && f.status == (int)RowState.Valid);
            if (blxDetail != null)
            {
                blxDetail.start_time = (int)startTime;
                blxDetail.end_time = (int)endTime;
                blxDetail.update_time = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now);
                apiToolDbContext.siger_project_tool_blx.Update(blxDetail);
            }
            else
            {
                var newData = new SigerProjectToolBlx
                {
                    company_id = companyId,
                    project_id = projectId,
                    machine_id = machineId,
                    spindle_name = spindleName,
                    program_no = programNo,
                    start_time = (int)startTime,
                    end_time = (int)endTime,
                    create_time = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now),
                    update_time = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now),
                    status = (int)RowState.Valid
                };
                apiToolDbContext.siger_project_tool_blx.Add(newData);
            }
            //记录日志
            var logData = new SigerProjectToolBlxLog
            {
                machine_id = machineId,
                spindle_name = spindleName,
                program_no = programNo,
                start_time = (int)startTime,
                end_time = (int)endTime,
                study_user = userID.ToString(),
                create_time = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now)
            };
            apiToolDbContext.siger_project_tool_blx_log.Add(logData);
        }
        public List<OutLineStudyList> GetOutLineStudyList(int sectionID,string programNo, int projectID, int page, int pagesize, out int totalCount)
        {
            var mids = GetMachineIds(sectionID, projectID);

            Expression<Func<OutLineStudyList, bool>> Funcat = f => true;
            var query = from m in apiToolDbContext.siger_project_machine
                        join sp in apiToolDbContext.siger_project_tool_spindle_true on m.id equals sp.equipid
                        join tl in apiToolDbContext.siger_project_tool_cutter_location_true on sp.id equals tl.spindleid
                        join blxc in apiToolDbContext.siger_project_tool_blx_cutter on m.id equals blxc.machine_id
                        join u in apiToolDbContext.siger_project_user on blxc.userid equals u.mid
                        where m.projectid == projectID && m.status == (int)RowState.Valid && sp.status == (int)RowState.Valid && tl.status == (int)RowState.Valid
                        && mids.Contains(m.id) && tl.is_processing_program != (int)ProcessProgram.NoConfig
                        && blxc.project_id == m.projectid && blxc.machine_id == m.id && blxc.spindle_name == sp.name && blxc.cutter_location_name == tl.name && blxc.program_no == (tl.is_processing_program == (int)ProcessProgram.MainProgram ? tl.programno : tl.subprogramno)
                        select new OutLineStudyList
                        {
                            machine_id=m.id,
                            machine_name=m.title,
                            machine_code=m.code,
                            spindle_name=sp.name,
                            cutter_location_name=tl.name,
                            program_no=blxc.program_no,
                            type=blxc.type,
                            count=blxc.count,
                            uid=blxc.userid,
                            userName=u.name,
                            start_time= UnixTimeHelper.ConvertStringDateTime(blxc.start_time.ToString()).ToString("yyyy-MM-dd HH:mm:ss"),
                            end_time = UnixTimeHelper.ConvertStringDateTime(blxc.end_time.ToString()).ToString("yyyy-MM-dd HH:mm:ss"),
                            

                        };

            if (!string.IsNullOrEmpty(programNo))
            {
                Funcat = f => f.program_no.Contains(programNo);
            }
            var groupData = query.Where(Funcat)
                .GroupBy(x => new { x.machine_id, x.machine_name, x.machine_code, x.spindle_name, x.cutter_location_name, x.program_no, x.type, x.count, x.uid, x.userName, x.start_time, x.end_time })
                .Select(g => new OutLineStudyList
                {
                    machine_id=g.Key.machine_id,
                    machine_code=g.Key.machine_code,
                    machine_name=g.Key.machine_name,
                    spindle_name=g.Key.spindle_name,
                    cutter_location_name=g.Key.cutter_location_name,
                    program_no=g.Key.program_no,
                    type=g.Key.type,
                    count=g.Key.count,
                    uid=g.Key.uid,
                    userName=g.Key.userName,
                    start_time=g.Key.start_time,
                    end_time=g.Key.end_time

                }).ToList();

            totalCount = groupData.Count();

            return groupData.OrderBy(o => o.machine_id).ThenBy(o => o.spindle_name).ThenBy(o=>o.cutter_location_name).Skip((page - 1) * pagesize).Take(pagesize).ToList();

            //var mids = GetMachineIds(sectionID, projectID);
            //Expression<Func<OutLineStudyList, bool>> Funkey = f => true;
            //var dataQuery = from cb in apiToolDbContext.siger_project_tool_blx_cutter
            //                join m in apiToolDbContext.siger_project_machine
            //                on cb.machine_id equals m.id into tmp1
            //                from t1 in tmp1.DefaultIfEmpty()
            //                join ts in apiToolDbContext.siger_project_tool_spindle_true
            //                on new { equipid = cb.machine_id, name = cb.spindle_name } equals new { ts.equipid, ts.name }
            //                into ret
            //                from r in ret.DefaultIfEmpty()
            //                where mids.Contains(t1.id) && cb.status == (int)RowState.Valid &&
            //                     r.status == (int)RowState.Valid && t1.status == (int)RowState.Valid
            //                orderby cb.machine_id, cb.spindle_name, cb.cutter_location_name
            //                select new OutLineStudyList
            //                {
            //                    id = cb.id,
            //                    machine_id = t1.id,
            //                    spindle_name = cb.spindle_name,
            //                    cutter_location_name = cb.cutter_location_name,
            //                    start_time = UnixTimeHelper.ConvertStringDateTime(cb.start_time.ToString()).ToString("yyyy-MM-dd HH:mm:ss"),
            //                    end_time = UnixTimeHelper.ConvertStringDateTime(cb.end_time.ToString()).ToString("yyyy-MM-dd HH:mm:ss"),
            //                    program_no = cb.program_no,
            //                    machine_name = t1.title ?? "",
            //                    machine_code = t1.code ?? "",
            //                    count = cb.count,
            //                    type = cb.type,
            //                    uid = cb.userid,
            //                    userName = ""
            //                };

            //if (!string.IsNullOrEmpty(programNo))
            //{
            //    Funkey = f => f.program_no.Contains(programNo);
            //}
            //totalCount = dataQuery.Where(Funkey).Count();
            //var data = dataQuery.Where(Funkey).Skip((page - 1) * pagesize).Take(pagesize).ToList();
            //foreach (var item in data)
            //{
            //    var user = apiToolDbContext.siger_project_user.FirstOrDefault(f => f.status == (int)RowState.Valid && f.projectid == projectID && f.mid == item.uid);
            //    item.userName = user?.name ?? "";
            //}
            //return data;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="sectionId"></param>
        /// <param name="program"></param>
        /// <returns></returns>
        private IEnumerable<MachineSpinldeToolProgramInfo> GetLineMachineConfig(int projectId,int sectionId,string program)
        {
            var mids = GetMachineIds(sectionId, projectId);

            Expression<Func<MachineSpinldeToolProgramInfo, bool>> Funcat = f => true;
            var query = from m in apiToolDbContext.siger_project_machine
                        join sp in apiToolDbContext.siger_project_tool_spindle_true on m.id equals sp.equipid
                        join tl in apiToolDbContext.siger_project_tool_cutter_location_true on sp.id equals tl.spindleid
                        where m.projectid == projectId && m.status == (int)RowState.Valid && sp.status == (int)RowState.Valid && tl.status == (int)RowState.Valid
                        && mids.Contains(m.id) && tl.is_processing_program!=(int)ProcessProgram.NoConfig && m.category == (int)MachineCategory.NC
                        select new MachineSpinldeToolProgramInfo
                        {
                             ProjectId=m.projectid,
                             MachineId=m.id,
                             MachineCode=m.code,
                             MachineTile=m.title,
                             SpinldeName=sp.name,
                             CuterLocateName=tl.name,
                             Program= tl.is_processing_program ==(int)ProcessProgram.MainProgram ? tl.programno : tl.subprogramno

                        };
            
            if (!string.IsNullOrEmpty(program))
            {
                Funcat = f => f.Program.Contains(program);
            }
            
            return query.Where(Funcat).GroupBy(x=>new {x.ProjectId,x.MachineId,x.MachineTile,x.MachineCode ,x.SpinldeName,x.CuterLocateName,x.Program }).Select(g=>new MachineSpinldeToolProgramInfo {
                  ProjectId=g.Key.ProjectId,
                  MachineId=g.Key.MachineId,
                  MachineTile=g.Key.MachineTile,
                  MachineCode=g.Key.MachineCode,
                  CuterLocateName=g.Key.CuterLocateName,
                  SpinldeName=g.Key.SpinldeName,
                  Program=g.Key.Program

            }).AsEnumerable();
        }

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

            Expression<Func<ResponseToolConfig, bool>> Funcat = f => true;
            var query = from m in apiToolDbContext.siger_project_machine
                        join sp in apiToolDbContext.siger_project_tool_spindle_true on m.id equals sp.equipid
                        join tl in apiToolDbContext.siger_project_tool_cutter_location_true on sp.id equals tl.spindleid
                        join ls in apiToolDbContext.siger_project_level_section_machine on m.id equals ls.machine_id
                 
                        where m.projectid == projectID && m.status == (int)RowState.Valid && sp.status == (int)RowState.Valid && tl.status == (int)RowState.Valid
                        && mids.Contains(m.id) && tl.is_processing_program != (int)ProcessProgram.NoConfig
                    
                        select new ResponseToolConfig
                        {
                            Id=tl.id,
                            MachineId = m.id,
                            MachineDes=m.title,
                            Section=ls.section_id,
                            Program=tl.is_processing_program==(int)ProcessProgram.MainProgram?tl.programno:tl.subprogramno,
                            Spindle=sp.name,
                            Tool=tl.name,
                          
                            //Marktype=new Marktype()
                        };

            if (!string.IsNullOrEmpty(programNo))
            {
                Funcat = f => f.Program.Contains(programNo);
            }
            totalCount = query.Count(Funcat);
            return  query.Where(Funcat).Skip((page - 1) * pagesize).Take(pagesize).ToList();

        }


    }
}