/*
    NAME: 
    DESCRIPTION: matrix改名和排序
    PARAMETER:
	[
		{
			name : 'customer',
			title : 'CUSTOMER 名',
			type : 'LineEdit',
			property : {tool_tip : '客户名称'}
        },
        {
            name : 'job_name',
			title : '料号名',
			type : 'LineEdit',
			property : {tool_tip : '料号名'}
        }
    ]

    VERSION_HISTORY:
	V1.00 2020 3-30 Scott
	
    HELP:
	<html><body bgcolor="#DDECFE">
		<font size="3" color="#003DB2"><p>功能简介</p></font>
		  <p> matrix改名和排序</p>
		  <br>
		<font size="3" color="#003DB2"><p>参数配置</p></font>
		 <p> matrix改名和排序规则 </p>
		<font size="3" color="#003DB2"><p>注意事项</p></font>
		  <p> ● 无 </p>
		  <br>
	</body></html>	
*/

// 引入模块 包
var $ = require('topcam.scriptfunc').argv();
var fs = require('fs');
var _ = require('lodash');
var IKM = $.ikm;
var GEN = $.gen;
var GUI = $.gui;
var Job = $.job;

try {
    var mode = "use" // develop
    var par = $.par;
    par = {job_name:"2", customer:"ats"}  // !! tmp
    var cfg = JSON.parse(IKM.select_value({table:'pub_conf',field:'json_data',where:{path : 'cam/input_data'}}));  // 读取配置文件
    var useCfg = cfg[par.customer.toLowerCase()].formatData; 
    if(!useCfg){throw "config error"}
    var job = par.job_name
    if(!GEN.isJobExists({job:job})){ throw "job "+ job+ " is not exist" }
    if(!GEN.isJobOpen({job:job})){GEN.openJob({job:job})}
    if(GEN.checkInout({job:job,mode:"test"}) != 0 && mode != "develop"){ throw "the job check" }
    GEN.checkInout({job:job,mode:"out"});
    if(useCfg.hasOwnProperty("mergeDrill")){   // todo
        mergeDrill({job:job})
    }
    if(mode=="develop"){ IKM.msg("rename")}
    if(useCfg.rename){
        reName({job:job,rule:useCfg.rename})
    }
    if(mode=="develop"){ IKM.msg("sort")}
    if(useCfg.sort){
        var err = sortLayer({job:job, rule:useCfg.sort});  // 排序
        if (err) {throw err}
    }
    if(mode=="develop"){ IKM.msg("setDrill")}
    if(useCfg.setDrill && /^yes$/.test(useCfg.setDrill.info)){
        setDrill({job:job}); // 设置钻孔
    }
    // finally
    if (/^yes$/ig.test(useCfg.autoSave)) { GEN.saveJob({ job: job }); }
    GEN.checkInout({job:job,mode:"in"});
    GEN.closeJob({job:job})

    return 'Done';
}
catch (error) {
    GUI.msg(error);
    return 'Error';
}

function reName(props) { // 改名 par{job:要改名的料号, rule: {要改名的规则}
    var job = props.job
    if(Array.isArray(props.rule)){
        props.rule = {rule:  props.rule }
    }
    var matrix = GEN.getMatrix({job:job});  // 获取matrix
    var matrixNames = Object.keys(matrix)  // 获取数组 matrix的name
    var signalCount = matrixNames.reduce(function(a,b){
        if(matrix[b].context == "board" && matrix[b].layer_type=="signal"){
            a++
        }
        return a
    },0)
    var reNameList = [];  // 记录匹配程度最高的改名结果
    Object.keys(props.rule).forEach(function(key){
        var rule = props.rule[key];
        var renames =  getRenameCount(matrixNames,rule, signalCount);  // 根据规则 和 matrixNames 的到更改名称数据
        if(renames.length > reNameList.length){  // 找到匹配规则最多的
            reNameList = renames; 
        }
    })
    // 更改层名
    reNameList.forEach(function(v){
        if(v.orig_name !== v.new_name){
            GEN.renameLayer({job:job,layer:v.orig_name,new_name:v.new_name})
        }
    });
}

function getRenameCount(names,rule,signalCount){  // 返回改名匹配结果
    var res = names.reduce(function(res, name){
        rule.map(function(rule){
            if(rule.orig_name === name){
                res.push({orig_name:name, new_name:rule.new_name});
            } else if(eval("/^"+rule.orig_name+"$/ig.test(name)")) {
                if(/\(.*\)/ig.test(rule.orig_name)){
                    var exec = eval("/"+rule.orig_name+"/ig.exec(name)").slice(1)
                    var new_name = rule.new_name;
                    var index = 0;
                    exec.forEach(function(v,i){
                        if(/(after)/.test(new_name)){
                            new_name = new_name.replace("(after)", Number(v)+1);
                        }
                        if(/(last)/.test(new_name)){
                            new_name = new_name.replace("(last)",signalCount);
                        }
                        new_name = new_name.replace("("+(i+1)+")", v);
                        if(rule.tp && /\d+/.test(v)){
                            if(v==1){ new_name = "top" }
                            index = v > index ? v : index
                        }
                    })
                    if(rule.tp){
                        res.push({orig_name:name, new_name:new_name, index:index});
                    }else{
                        res.push({orig_name:name, new_name:new_name});
                    }
                } else {
                    res.push({orig_name:name, new_name:rule.new_name});
                }
            }
        })
        return res
    }, [])
    var tpIndex = {i: -1, value: 0};
    res.forEach(function(v,i){
        if(v.index && v.index > tpIndex.value){
            tpIndex.i = i    
            tpIndex.value = v.index    
        }
    })
    if(tpIndex.i >= 0){
        res[tpIndex.i].new_name = "bottom"
    }
    return res
}

function sortLayer(props){  // 排序方法  {job:要排序的料号, rule: {要改名的规则}
    var job = props.job
    var matrix = GEN.getMatrix({job:job});
    var matriNames = Object.keys(matrix)
    // 找出所有排序规则中契合度最高的
    var ruleKey = {}
    Object.keys(props.rule).forEach(function(key){
        var rule = props.rule[key]
        ruleKey[key] = 0
        var regs = rule.map(function(item){
            return new RegExp(item.name,'ig')
        })
        matriNames.forEach(function(name){
            var isSort = regs.reduce(function(a,b){
                if(b.test(name)){a = true}    
            return a}, false)
            if(isSort){ruleKey[key]++}
        })
    })
    var maxRule = {key:"", value: 0}
    Object.keys(ruleKey).forEach(function(key){
        var value = ruleKey[key]
        if (value>=maxRule.value){
            maxRule.key = key
            maxRule.value = value
        }
    })
    if(props.rule[maxRule.key]){props.rule = props.rule[maxRule.key]}else{return "sort rule error"}
    var matriName = Object.keys(matrix).sort(function(a,b){return matrix[a].row - matrix[b].row})
    var matrixFirst = matriName[0];  // 记录matrix中第一位
    var sortNames = [];
    var miscName = matriName.filter(function(name){  // 找出需要排序的名称列表
        var flag = true;
        props.rule.forEach(function(item,i){
            var evalReg = "/^"+item.name+"$/ig.test(name)";
            if(name == item.name || eval(evalReg)){
                flag = false;
                if(name === item.name){
                    var _item = JSON.parse(JSON.stringify(item));
                    _item.value = i;
                    sortNames.push(_item);
                } else {
                    var _item = JSON.parse(JSON.stringify(item));
                    _item.value = i;
                    var str = "/^"+ item.name +"$/ig.exec(name)"
                    _item.value2 = eval(str)[1] - 0;
                    _item.name = name;
                    sortNames.push(_item);
                }
            }
        });
        return flag;
    })
    miscName.forEach(function(n){ 
        if(matrix[n].context == 'board'){
            GEN.matrixLayerAttr({job:job,layer:n,context:'misc'}) 
        }
    })
    sortNames = sortNames.sort(function(a,b){
        return a.value - b.value || a.value2 - b.value2
    })
    // 排序
    if(sortNames.length){
        if(sortNames[0].name !== matrixFirst) {  // 如果第一位和matrix中第一位不同,先把第一位插入到最前面
            GEN.matrixMoveRow({ job:job,layer:sortNames[0].name,before:matrixFirst })
        }
        sortNames.forEach(function(v,i,arr){
            var layer = matrix[v.name];
            if(i !== 0){
                GEN.matrixMoveRow({ job:job,layer:v.name,after:arr[i-1].name })             
            }
            if(v.context !== layer.context || v.type !== layer.layer_type || v.polarity !== layer.polarity){
                GEN.matrixLayerAttr({job:job,layer:v.name,context:v.context,type:v.type,polarity:v.polarity});
            }
        })
    }
}

function setDrill(props){   // 设置钻孔
    var job = props.job
    var martrix = GEN.getMatrix({job:job});
    // 获取所有的钻孔层
    var drillLayer = Object.keys(martrix).filter(function(v){
        return martrix[v].layer_type == "drill" && martrix[v].context == "board"
    })
    // 获取所有single层
    var signalLayer = Object.keys(martrix).sort(function(a,b){return Number(martrix[a].row) - Number(martrix[b].row)}).filter(function(v){
        return martrix[v].layer_type == "signal" && martrix[v].context == "board"
    })
    var layerCount = GEN.getLayerCount({job:job})
    // findSignal 根据传入的数字找到对应的signal层 如 1 => top ; 2 => layer_2 
    function findSignal(num){
        var res = signalLayer.filter(function(v){
            var vnum = 0;
            if(/\d/.test(v)){
                var tmp = /(\d+)/ig.exec(v);
                vnum = tmp? Number(tmp[1]) : 0;
            }
            return num === vnum
        })
        return res[0];
    }
    function doDrill(drills){  // 分析钻孔层
        return drills.map(function(v){
            if(v == "drill"){
                return {start:signalLayer[0], end:signalLayer[signalLayer.length - 1], layer:v}
            } else {
                var tmp = /(\d+).(\d+)/ig.exec(v);
                if(tmp){
                    var start = Number(tmp[1]) === 1? 'top':findSignal(Number(tmp[1])); 
                    var end = Number(tmp[2]) === layerCount? 'bottom': findSignal(Number(tmp[2]));
                    return {start:start, end:end, layer:v}
                } else {
                    return 0;
                }
            }
        })
    }
    var drillSetList = doDrill(drillLayer);   // 分析得到钻孔设置结果
    drillSetList = drillSetList.filter(function(v){return v!==0})
    drillSetList.forEach(function(v){
        GEN.matrixLayerDrill({job:job,layer:v.layer,start:v.start ,end:v.end})
    })
}

function mergeDrill(props){ // 合并钻孔
    var newdrills = []
    var job = props.job;
    var step = GEN.getStepList({job:job})[0];
    var maxDrill = {name:"",value:0};
    function getDrl(str){
        var num = /(\d+)-(\d+)/ig.exec(str);  // 匹配出 num-num
        var tmp = [];
        for(var i = Number(num[1]);i<num[2];i++){
            if(i == 1){
                maxDrill = Number(num[2]) >  maxDrill.value? {name:str,value:Number(num[2])} : maxDrill;
            }
            tmp.push("L"+i+"-"+(i+1));
        }
        return tmp;
    } 
    var matrix = GEN.getMatrix({job:job});
    GEN.openStep({job : job,name:step});
    for(var key in matrix){
        var val = matrix[key];
        if(val.layer_type == "drill"){
            var mergeTo = getDrl(val.name) // 要合并到的地方
            mergeTo.forEach(function(layerName){
                if(GEN.isLayerExists({job : job ,layer:layerName.toLowerCase()}) && newdrills.indexOf(layerName.toLowerCase()) < 0){
                    GEN.deleteLayer({job:job, layer:layerName.toLowerCase()})
                }
                if(!GEN.isLayerExists({job : job ,layer:layerName.toLowerCase()})){
                    GEN.createLayer({job:job,layer:layerName.toLowerCase(),conext:'board',type:val.layer_type});
                    newdrills.push(layerName.toLowerCase())
                }
                GEN.workLayer({name:layerName.toLowerCase(),display_number:1,clear_before:'yes'});
                GEN.copyLayer({source_job:job ,mode:'append',source_step:step,source_layer:val.name,dest_layer:layerName.toLowerCase()});
            })
        }
    }
    // 合并到maxDrill独立合并
    GEN.createLayer({job:job,layer:"b1-"+maxDrill.value,conext:'board',type:'drill'});
    GEN.workLayer({name:"b1-"+maxDrill.value,display_number:1,clear_before:'yes'});
    GEN.copyLayer({source_job:job ,mode:'append',source_step:step,source_layer:maxDrill.name,dest_layer:"b1-"+maxDrill.value});
    GEN.affectedLayer({affected:"no",mode:"all"});
    GEN.closeStep();
    return this;
}