/**
 * Created by zhang on 2020/7/20
 */
module.exports={
  getOptions,
  getDataByCondition,
  getClassByAreaID,
  mutiApplyInfoPrice
};

const mongoose = require('mongoose');
let infoLibModel = mongoose.model("std_price_info_lib");
let infoClassModel = mongoose.model("std_price_info_class");
let infoItemsModel = mongoose.model("std_price_info_items");
let infoAreasModel = mongoose.model("std_price_info_areas");
let unitPriceModel = mongoose.model("unit_price"); 
let _ = require("lodash");
let gljUtil = require('../../../public/web/gljUtil');
const scMathUtil = require('../../../public/scMathUtil').getUtil();
let projectfacade = require('./project_facade');
// 载入模块
var Segment = require('segment');
// 创建实例
var segment = new Segment();
// 使用默认的识别模块及字典，载入字典文件需要1秒，仅初始化时执行一次即可
segment.useDefault();

let nodejieba = require('../../dict/jieba');

let nameWeightMap ={ 
 // '普通':-99
}



async function getOptions(data,compilation){//data 是预留对象，暂时不用
  let compilationID = compilation._id;
  let areaMap={};
  let periodMap={};
  let areas =await infoAreasModel.find({"compilationID":compilationID}).lean();

  let libList = await infoLibModel.find({"compilationID":compilationID}).lean();
  for(let l of libList){
    // for(let area of l.areas){
    //   if(!areaMap[area]) areas.push(area);
    // }
    //2020-05
    let periodArray = l.period.split("-");
    periodMap[periodArray[0]]?periodMap[periodArray[0]].push(periodArray[1]):periodMap[periodArray[0]]=[periodArray[1]]
  }
 
 
  for(let key in periodMap){
    periodMap[key] = _.sortBy(periodMap[key]);
  }
  return {areas:areas,periodMap:periodMap}
}

async function getClassByAreaID(data,compilation){
  //要先知道根据期数和编办查找库ID
  let newList = [];
  let lib = await infoLibModel.findOne({compilationID:compilation._id,period:data.period})
  if(lib){
    let tList =await getClassList(data.areaID,lib.ID);
    newList.push(...tList);
    if(data.commonInfoPriceID){
      cList = await getClassList(data.commonInfoPriceID,lib.ID);
      newList.push(...cList);
    }  
  }
  


  async function getClassList(areaID,libID){
    let temList = [];
    let infoClass =  await infoClassModel.find({areaID:areaID,libID:libID}).lean();
    let parentMap=_.groupBy(infoClass, 'ParentID');
    for(let key in parentMap){
      parentMap[key] = projectfacade.sortChildren(parentMap[key]);
    }
    
    if(parentMap && parentMap['-1']){
      getChildern(parentMap['-1'],temList,parentMap)
    }
    return temList;
  }


  function getChildern(children,list,pm){
    for(let c of children){
      list.push(c);
      if(pm[c.ID]){
        getChildern(pm[c.ID],list,pm)
      }
    }
  }
  return newList;
}

async function getDataByCondition(data,compilation){
  let result = {};
  data.condition["compilationID"] = compilation._id;
  //特殊处理重庆的，地区选择非“通用”时，搜索范围应是当前选择的地区，加上“通用”中的信息价。
  if (data.condition.commonInfoPriceID) { 
    let idArray = [data.condition.areaID,data.condition.commonInfoPriceID];
    data.condition.areaID = {$in: idArray}
    delete data.condition.commonInfoPriceID;
  }

  //根据地区+期数+材料编号的前4位与信息价材料的分类编号匹配，如果有数据，则显示数据出来。
  //先按编号匹配
  if (data.code) { 
    result = await getDataByCode(data.code, data);
    if (result.totalSize > 0) return result;

    //如果分类编码有结果，但是确没有匹配的条数，说明关键字没匹配上，直接返回没有信息价
    if(result.allItems > 0 && result.totalSize === 0){
      return result;
    }

  }
 
  //编号匹配不上的情况：
  //有关键字的情况
  if (data.keyWord) { 
    return await getDataByKeyWord(data.keyWord,data);
  } 

  //查询所有的情况
  if(data.lastID){ //有最后一行说明是查询下一页
    data.condition["_id"] = {$gt:mongoose.Types.ObjectId(data.lastID)};
  }else{
    result.totalSize = await infoItemsModel.find(data.condition).count();
  }
  result.items = await infoItemsModel.find(data.condition).lean().sort({"_id":1}).limit(50);
  return result;
}


async function getDataByCode(code, data) { 
  let condition = { ...data.condition };
  condition.code = code;
 /*  
  2021-03-31 先按编号去取，所有匹配结果再过滤，不能再分类了
 let totalSize = await infoItemsModel.find(condition).count();
  if (data.lastID) { //有最后一行说明是查询下一页
    condition["_id"] = {$gt:mongoose.Types.ObjectId(data.lastID)};
  }
  let items = [];
  if (totalSize > 0) { 
    items = await infoItemsModel.find(condition).lean().sort({"_id":1}).limit(50);
  } */
   
 //新需求 --------- 
  let  allItems = await infoItemsModel.find(condition).lean().sort({"_id":1});
  let items = [];
  if(data.keyWord && allItems.length > 1){
    for(let item of allItems){
      if(item.name.indexOf(data.keyWord) != -1) items.push(item) //有完全匹配的，就不用编码下的返回所有数据了
    }
  }
  //没有完全匹配的，分词匹配关键字
  if (items.length === 0 && data.keyWord){
    let nameArray =  nodejieba.cut(data.keyWord);
    nameArray = cusSegment(nameArray,data.keyWord);
    let result = getMatchPrice(allItems,nameArray);
    items = result.items;
  }

  let totalSize = items.length;

  //新需求结束 --------- 

  return {totalSize,items,allItems}
}


async function getDataByKeyWord(keyword, data) {
  //先按全字匹配
  let fullResult =await getDataByFullKeyWord(keyword, data);
  if(fullResult.totalSize > 0) return fullResult;

  //如果没有才按模糊匹配
 return await getDataByFuzzyMatch(keyword, data);
}


//按全关键字匹配
async function getDataByFullKeyWord(keyword, data){
  let items = [];  
  data.condition.name =  new RegExp(keyword);
  items = await infoItemsModel.find(data.condition).lean().sort({"_id":1});
 
  delete data.condition.name;
  return{totalSize:items.length,items}
}



function handelThreeWord(word){
  let arr = [];
  getArr(word[0]+word[1],arr);
  getArr(word[1]+word[2],arr);
  if(arr.length > 0) return arr;
  return[word];

  function getArr(tem,list){
    let nameArray = segment.doSegment(tem, {
      simple: true, //不返回词性
      stripPunctuation: true //去除标点符号
    });
    //说明是一个词
    if(nameArray.length == 1) list.push(tem)
  }
}

function getShortNameArray(nameArray){
  let newArray = [];
  for(let n of nameArray){
    if(n.length >= 5){
      newArray.push(...nodejieba.cutSmall(n,3)) 
    }else{
      newArray.push(n);
    }
  }
  return newArray;

}

function getMatchPrice(allInfoPrice,nameArray,needHandleLongWord = true){
  let items = [];
  let maxNum = 0;//最大匹配数
  let matchMap = {};//匹配储存
  let handleLongWord = false;
  if(needHandleLongWord){
    for(let na of nameArray){
      if(na.length >= 5) handleLongWord = true;
    }
  }
  
  for (let info of allInfoPrice) { 
    //specs
    let mstring = info.name + info.specs;
    mstring = mstring.replace(/混凝土/g, "砼");
    info.mstring = mstring;
    let matchCount = 0;
    for (let na of nameArray) { 
      if (mstring.indexOf(na) != -1) { 
        matchCount++;
        if(needHandleLongWord && na.length >= 5) handleLongWord = false//有5个字的，并且匹配上了，这里就为false不用再处理一次了
      }
    }  
    if (matchCount > 0) { 
      matchMap[matchCount] ? matchMap[matchCount].push(info) : matchMap[matchCount] = [info];
      if (matchCount > maxNum) maxNum = matchCount;
    }
  }
  if (maxNum > 0) items = matchMap[maxNum];
  totalSize = items.length
  return {totalSize,items,handleLongWord};
}

//自定义特殊处理
function cusSegment(nameArray,keyword){
  let temArr = [];
  for (let a of nameArray) { 
     //混凝土 和 砼 统一认成砼
    if (a == "混凝土") a = '砼';
    if(a == '砼'||a == '砖' ){
      temArr.push(a);
    }else if(a.length > 1){
      //如果是三个字的词，优先识别成两个字
      if(a.length == 3){
        let sArr = handelThreeWord(a);
        temArr.push(...sArr);
      }else{
        temArr.push(a);
      }
    }
  }
  if (keyword.length == 1 && temArr.length == 0) temArr.push(keyword);
  return temArr;
}

//模糊匹配
async function getDataByFuzzyMatch(keyword, data){

  let nameArray = [];
  if (keyword.length < 3) {
    nameArray.push(keyword)
  } else { 
    nameArray = nodejieba.cut(keyword)
  }
 
  //自定义处理
  nameArray = cusSegment(nameArray,keyword);

  console.log(nameArray);


  let allInfoPrice = await infoItemsModel.find(data.condition).lean().sort({"_id":1});

  let {totalSize,items,handleLongWord}  = getMatchPrice(allInfoPrice,nameArray)
  if(handleLongWord === true){
    nameArray = getShortNameArray(nameArray);
    console.log(`二次匹配:[${nameArray}]`);
    let newResult  = getMatchPrice(allInfoPrice,nameArray,false)
    totalSize = newResult.totalSize;
    items = newResult.items;
  }

  //关键词按权重排序，为了给结果排序
  nameArray = _.sortBy(nameArray,(name)=>{
    if(nameWeightMap[name]) return nameWeightMap[name]*-1;//sortBy是升序排序，我们要的是权重越小排到越后即倒序 所以这里乘以-1
    return 1
  })

  //按匹配位置排序 如[ '橡胶', '胶圈', '给水' ] 先显示橡胶
  items = _.sortBy(items,(item)=>{
    let ms = item.mstring;
    for(let i = 0;i < nameArray.length;i ++){
      if (ms.indexOf(nameArray[i]) != -1) return i;
    }
  })
  return {totalSize,items}
}


async function mutiApplyInfoPrice(data,compilation){
  data.condition["compilationID"] = compilation._id;
  let infoPrices = await infoItemsModel.find(data.condition).lean();
  let tasks = [];
  let projectGLJMap = {};
  for(let info of infoPrices){
    let index = gljUtil.getIndex(info,["name","specs","unit"]);
    if(data.pgljMap[index]){
      for(let obj of data.pgljMap[index]){
        let infoPrice = gljUtil.getInfoMarketPrice(info,data.taxType);
        infoPrice = scMathUtil.roundToString(infoPrice,data.decimal);
        let doc = {'market_price':infoPrice,'priceFrom':data.priceFrom};
        let task = {
          updateOne:{
              filter:{'id':obj.unitPriceID},
              update:doc
          }
        };
        tasks.push(task);
        projectGLJMap[obj.pgljID] = {index:obj.fullIndex,doc:doc};
      }  
    }
  }
  if(tasks.length > 0) await unitPriceModel.bulkWrite(tasks);
  return projectGLJMap;
}

