/*
    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 = "develop" // develop
	var config = require("../config.js")   // 读取配置文件
	var par = {    // todo
		job:"i4",
		customer: "Customer_2"
	}
	var job = par.job || Job;
    if(_.isEmpty(job)) throw "没有传入料号名!";
	job = job.toLowerCase()
	var custCfg = config.customer[par.customer]	// 获取客户配置
	var step = custCfg.step.toLowerCase()	// 获取pcs_step
	// 料号验证
    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(config.hasOwnProperty("merge_drill")){ // todo
	// 	mergeDrill({job:job})
	// }
	// start    martix_tl_name
	var matrix = GEN.getMatrix({job:job})
	var tl_name_matrix = tlNameMatrix({matrix:matrix,tl_name:custCfg.tl_name})   // 给matrix信息添加tl_name



	tl_name_matrix.forEach(function(item){  // * 调试
		IKM.add({name:item.name, tl_name:item.tl_name})
	})
	IKM.add("",1)

	var format_cfg = config.data_format   // 拿到数据标准化配置

	// 排序和设属性
	var ret = sortLayer({job:job, rule:format_cfg, matrix:tl_name_matrix})
	if(ret.err){throw err}
	var after_sort_matrix = ret.sortNames
	// 设置钻孔
	err = setDrill({job:job, matrix:after_sort_matrix})
	if(err){throw err}
	
	// 改名
	err = reName({job:job, matrix:after_sort_matrix, cfg:format_cfg})
	if(err){throw err}

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

function tlNameMatrix(props){  // 设置标准名
	var matrix = props.matrix
	var tlname_rules = []
	props.tl_name.forEach(function(item){
		if(typeof item.orig_name == "string"){
			tlname_rules.push(item)
		} else {
			item.orig_name.forEach(function(name2){
				tlname_rules.push({
					orig_name: name2,
					tl_name: item.tl_name
				})
			})
		}
	})
	var res = Object.keys(matrix).map(function(key){  // 将matrix信息添加tl_name 如果没有tl_name 就返回原信息
		var val = matrix[key]
		if(val.hasOwnProperty("tl_name")){delete val.tl_name}
		var tlRule = tlname_rules.filter(function(rule){
			if(rule.orig_name === key){return true}
			var reg = new RegExp(rule.orig_name,"ig")
			return reg.test(key)
		})
		if(tlRule.length == 0){return val}
		for(var i=0;i<tlRule.length;i++){
			if(tlRule[i].orig_name === key){return _.assign(val,{tl_name:tlRule[0].tl_name})}
		}
		var reg = new RegExp(tlRule[0].orig_name,"ig")
		var tmp = reg.exec(key)
		if(tmp && tmp.length){
			var replaceArr = tmp.slice(1)
			var tl_name = tlRule[0].tl_name
			var params = {}
			for(var i = 0; i<replaceArr.length;i++){
				params["$"+(i+1)] = replaceArr[i]
			}
			replaceArr.forEach(function(v,i){
				tl_name = tl_name.replace("($"+(i+1)+")",v)
			})
			tl_name = replaceTlName(tl_name)
			function replaceTlName(name){
				var tmp = /(\([^)]*\))/ig.exec(name)
				if(!tmp){ return name }
				var param_arr = tmp[1].match(/\$\d+/ig)
				var newname = tmp[1]
				param_arr.forEach(function(v){
					newname = newname.replace(new RegExp("\\"+v,"ig"), params[v])
				})
				newname = name.replace(tmp[1],eval(newname))
				return replaceTlName(newname)
			}
			return _.assign(val,{tl_name:tl_name})
		}else {
			return _.assign(val,{tl_name:tlRule[0].tl_name})
		}
	})
	return res
}

function sortLayer(props){  // 排序方法  {job:要排序的料号, rule: {要改名的规则}
    var job = props.job
	var matrix =  GEN.getMatrix({job:job})
	var tl_matrix = props.matrix
	var matrixName = Object.keys(matrix).sort(function(a,b){return matrix[a].row - matrix[b].row})
    var matrixFirst = matrixName[0];  // 记录matrix中第一位
	var sortNames = [];
    var miscName = tl_matrix.filter(function(value){  // 找出需要排序的名称列表
		var flag = true;
		if (!value.tl_name || value.tl_name == ""){return true}
		var tl_name = value.tl_name
        props.rule.forEach(function(item,i){
            var evalReg = "/"+item.tl_name+"/ig.test(tl_name)";
            if(tl_name == item.tl_name || eval(evalReg)){
                flag = false;
                if(tl_name === item.tl_name){
                    var _item = JSON.parse(JSON.stringify(item));
					_item.value = i;
					_item.name = value.name
					_item.rule = item.tl_name
                    sortNames.push(_item);
                } else {
                    var _item = JSON.parse(JSON.stringify(item));
                    _item.value = i;
					var str = "/"+ item.tl_name +"/ig.exec(tl_name)"
					_item.value2 = eval(str).pop() - 0;
					_item.name = value.name
					_item.rule = item.tl_name
                    _item.tl_name = tl_name;
                    sortNames.push(_item);
                }
            }
        });
        return flag;
	}).map(function(v){return v.name})
    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){
            if(i !== 0){
                GEN.matrixMoveRow({ job:job,layer:v.name,after:arr[i-1].name })             
            }
            GEN.matrixLayerAttr(_.assign({job:job,layer:v.name},v.attr));
        })
	}
	return {
		sortNames:sortNames
	}
}

function setDrill(props){   // 设置钻孔
    var job = props.job
	var matrix = props.matrix
	
    // 获取所有的钻孔层
    var drillLayer =matrix.filter(function(v){
        return (v.attr.type == "drill" || v.attr.type == "rout") && v.attr.context == "board"
    })
    // 获取所有single层
    var signalLayer =matrix.filter(function(v){
        return v.attr.type == "signal" && v.attr.context == "board"
	})
	var layerCount = GEN.getLayerCount({job:job})
    // findSignal 根据传入的数字找到对应的signal层 如 1 => top ; 2 => layer_2 
    function findSignal(num){
        return signalLayer[Number(num-1)].name
	}
    function doDrill(drills){  // 分析钻孔层
        return drills.map(function(v){
            if(v.name == "drill" || v.name=="rout"){
                return {start:findSignal(1), end:findSignal(layerCount), layer:v.name}
            } else {
                var tmp = /(\d+)-(\d+)/ig.exec(v.tl_name);
                if(tmp){
                    var start = findSignal(tmp[1]); 
                    var end = findSignal(tmp[2]); 
                    return {start:start, end:end, layer:v.name}
                } 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 reName(props) { // 改名 par{job:要改名的料号, rule: {要改名的规则}
    var job = props.job
	var matrix = props.matrix
	var cfg = props.cfg
	matrix = matrix.filter(function(v){return v.name != v.new_name})
	var rename_list = matrix.map(function(item){
		var new_name;
		var tl_name = item.tl_name
		var rule = item.rule
		if(rule === tl_name){
			new_name = item.new_name
		} else {
			var reg = new RegExp(rule,"ig")
			var tmp = reg.exec(tl_name)
			if(!tmp){return undefined}
			var replaceArr = tmp.slice(1)
			new_name = item.new_name
			var params = {}
			for(var i = 0; i<replaceArr.length;i++){
				params["$"+(i+1)] = replaceArr[i]
			}
			replaceArr.forEach(function(v,i){
				tl_name = tl_name.replace("($"+(i+1)+")",v)
			})
			new_name = replaceTlName(new_name)
			function replaceTlName(name){
				var tmp = /(\([^)]*\))/ig.exec(name)
				if(!tmp){ return name }
				var param_arr = tmp[1].match(/\$\d+/ig)
				var newname = tmp[1]
				param_arr.forEach(function(v){
					newname = newname.replace(new RegExp("\\"+v,"ig"), params[v])
				})
				newname = name.replace(tmp[1],eval(newname))
				return replaceTlName(newname)
			}
		}
		return {
			orig_name: item.name,
			new_name: new_name
		}
	})
	rename_list = rename_list.filter(function(v){
		var flag = true
		if(!v){flag = false}
		if(!v.orig_name || !v.new_name ){flag = false}
		return flag
	})
	rename_list.forEach(function(v){
        if(v.orig_name !== v.new_name){
            GEN.renameLayer({job:job,layer:v.orig_name,new_name:v.new_name})
        }
    });
}

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+)\.drl/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" && /(\d+)-(\d+)\.drl/ig.test(val.name)){
            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()});
            })
        }
    }
    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.clearLayers();
    GEN.closeStep();
}
