/*
NAME: 
DESCRIPTION: 钻孔输出;
PARAMETER:
    [
		{
			name : 'step_filter',
			title : '工作step',
			type : 'LineEdit',
			property : {tool_tip : '过滤Step名称'},
		},
		{
			name : 'out_dir',
			title : '钻孔输出路径',
			type : 'LineEdit',
			property : {tool_tip : '例如: /output/drill'},
		},
		{
			name : 'cool_spread',
			title : '跳钻距离(um)',
			type : 'LineEdit',
			property : {tool_tip : '例如: 350'},
		},
		{
			name : 'reread_layer',
			type : 'RadioBox',
			title : '回读钻孔程式',
			property : {tool_tip:'未设定,则默认no',
						size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
			pack : {row:1,column:1},
		},
		{
			name : 'is_select_lyr',
			type : 'RadioBox',
			title : '是否选择层别',
			property : {tool_tip:'未设定,则默认no',
						size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
			pack : {row:1,column:1},
		},
		{
            name : 'auto_save',
			title : '自动保存',
            type : 'RadioBox',
            property : {
				item_list:[
					{name:'yes',text:'YES'},
					{name:'no',text:'NO'},
				],
				tool_tip:'是否自动保存料号开关'
			}
        }
	]
	
 VERSION_HISTORY:
	V1.00 2020-09-01 Scott Sun
	    1.新版本
		
 HELP:
 	<html><body bgcolor="#DDECFE">
		<font size="3" color="#003DB2"><p>功能简介</p></font>
		<p> 钻孔输出 </p>
		<br>
		<font size="3" color="#003DB2"><p>参数配置</p></font>
		<p> step信息 </p>
		<br>
		<font size="3" color="#003DB2"><p>注意事项</p></font>
		<p> 无 </p>
		<br>
	</body></html>	
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
var $ = require('topcam.scriptfunc').argv();
var fs = require('fs');
var _ = require('lodash');
var mode = $.ikm ? "topcam" : "aimdfm";
var IKM = $.ikm; 
if (IKM==undefined ) { IKM = require('topcam.ikm6')($) }
var GEN = $.gen;
var GUI = $.gui || {};
var Job = $.job || $.job_name;
var JobId = $.job_id;
var db = $.db || IKM.db
var PAR = {}
if ($.par) { PAR = $.par } else if ($.hasOwnProperty('script_parameter')){ PAR = JSON.parse($.script_parameter); }
if (mode === "aimdfm") {
	var database = require("topsin.database");
	database.addConnection($.conf.database_conf, "DFM");
	var QDfm = database.query("DFM");
	$.QDfm = QDfm;
	if ($.conf.product_type == "aimdfm") {
		QDfm.updateRow({ table: "pdm_aimdfm_task", data: { current_process_title: $.process_title }, where: { id: $.task_id } });
	}
}
require("topsin.genmath")
var genMath = new GenMath();
var gui = new NewGUI(GUI);
var Status = 'ok';
var resultData = [];
var par = PAR;
var default_par = {
	spread: 2000,
    step_filter:"step",
    out_dir:"C:/Users/Administrator/Desktop/jobs/demo",
	cool_spread:350,
	reread_layer:"no",
	is_select_lyr:"no",
	auto_save: "No",
	units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
var info = {};
var new_name = "new_test";
if(!fs.exists(par.out_dir)){
	IKM.msg("导出路径不存在");
	return "Canel"
}
par.out_dir += '/' + new_name;
fs.mkdir(par.out_dir);
var Step;
try {
	if(_.isEmpty(job)){throw "参数job不存在"} else { job = job.toLowerCase() }
	if(!GEN.isJobExists({job:job})){throw "料号"+job+"不存在"}
	
	// 选择工作step
	var workstep = getWorkStep()
	if(workstep.length == 0){throw "未找到工作step"}

	// 选择工作层
	var work_layers = select_work_layer();
	if(work_layers.length == 0){throw "未找到工作层"}

	// 确认涨缩信息
	var scale = get_scale_info({layers:work_layers});	// -----涨缩值信息确认
	par.scale = scale;

	workstep.forEach(function(step){
		Step = step;
		GEN.openStep({job:job,name:step});
		GEN.clearLayers();
		GEN.affectedLayer( {mode:'all',affected:'no'} );
		GEN.COM( "sel_options,clear_mode=clear_after,display_mode=all_layers,area_inout=inside,area_select=select,select_mode=standard,area_touching_mode=exclude");
		GEN.units( {type:par.units} );
		GEN.zoomHome();
		PAR.profile_limits = GEN.getProfileLimits({job:job,step:step,units:'mm'});
		PAR.profile_limits.xsize = Number(PAR.profile_limits.xsize);
		PAR.profile_limits.ysize = Number(PAR.profile_limits.ysize);
		PAR.profile_limits.xmin = Number(PAR.profile_limits.xmin);
		PAR.profile_limits.ymin = Number(PAR.profile_limits.ymin);
		PAR.profile_limits.xmax = Number(PAR.profile_limits.xmax);
		PAR.profile_limits.ymax = Number(PAR.profile_limits.ymax);
		PAR.profile_limits.xc = PAR.profile_limits.xsize/2-Math.abs(PAR.profile_limits.xmin);
		PAR.profile_limits.yc = PAR.profile_limits.ysize/2-Math.abs(PAR.profile_limits.ymin);
		PAR.sr = GEN.getSRLimits({job:job,step:step,units:'mm'});
		
		work_layers.forEach(function(layer){
			//钻孔输出
			var output_layer = job+'-'+layer+'-ori';   // Job.'-'.$layer.'-ori'
			drill_out({layer:layer,output_layer:output_layer,scale_x:PAR.scale[layer].x,scale_y:PAR.scale[layer].y});
			//钻孔程式编辑
			var new_layer='';
			if(PAR.scale[layer].x != 1 || PAR.scale[layer].y != 1){
				new_layer= new_name+'.'+layer+'X'+PAR.scale[layer]+'Y'+PAR.scale[layer].y
			}else{
				new_layer= new_name+'.'+layer;
			}
			var new_file = PAR.out_dir+'/'+new_layer;
			// 分割文件内容
			edit_nc_file({layer:layer,output_file:PAR.out_dir+'/'+output_layer,new_file:new_file,x:PAR.scale[layer].x,y:PAR.scale[layer].y});//drl_type:$drl_type
			//删除钻孔输出的临时文件
			// fs.unlink(PAR.out_dir+'/'+output_layer);
			//回读钻孔程式
			if( PAR.reread_layer =~ /yes/i){
				var new_layer_2 = new_layer;
				input_drill_program({layer:layer,file:PAR.out_dir+'/'+new_layer_2,new_layer:new_layer});//drl_type:drl_type,drl_side=>$drl_side
			}
		})



	})
	
	// 保存 
	if(/yes/ig.test(par.auto_save)){GEN.checkInout({job:job,mode:"out"}); GEN.saveJob({ job: job });GEN.checkInout({job:job,mode:"in"});GEN.closeJob({job:job});} else {GEN.checkInout({job:job,mode:"in"})}
	if (mode === "aimdfm") {
		$.QDfm.updateRow({table: "pdm_aimdfm_task",data: {progress: 33.33},where: { id: $.task_id }});
		if (GEN.hasError()) { Status = 'error';resultData.push({ type: "error", title: "GEN错误!", detail: [{ desc: _.join(GEN.STATUS, "\n") }] });
			return {status: Status,result_data: resultData};
		} else { resultData.push({ type: "info", title: "操作完成, 请注意检查!" }); return {status: Status,result_data: resultData}; }
	}else { return "Done" }
} catch (e) {
	IKM.msg(_.join(GEN.STATUS, "\n"));IKM.msg(e);Status = 'error';
    resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]});
    return (mode === "aimdfm") ? {status: Status, result_data: resultData} : "Error";
}

function NewGUI (gui) {
    this.msgBox = function(props){ // title  type  content  button
        props = props || {}
        return gui.msgBox(props.title || "title",props.type || "info",props.content || "content",props.button || ["ok", "cancel"]);
    }
    this.selectFromTreeview = gui.selectFromTreeview
    this.selectFile = function(props){ // "choose something", "*", true, "file", "/home/abby/fast_io"
        props = props || {}
        return gui.selectFile(props.title || "choose something",props.filter || "*",props.multiple || false, "file","");
    }
    this.selectSingle = function(props) {
        props = props || {}
        return gui.selectSingle({
            "title": props.title || "select",
            "list": props.list || [],
            "default": props["default"] || "",
            "columns": props.columns || 2,
            "gen":props.gen || GEN
        });
    }
    this.selectMultiple = function(props) {
        props = props || {}
        return gui.selectMultiple({
            "title": props.title || "select",
            "list": props.list || [],
            "defaultvalue": props["defaultvalue"] || [""],
            "defaultsize": props["defaultsize"] || [200, 100],
            "columns": props.columns || 2,
            "gen":props.gen || GEN
        });
    }
    this.selectFromTable = gui.selectFromTable
    this.snapScreen = gui.snapScreen
    this.imageViewer = gui.imageViewer
    this.inputBox = gui.inputBox
    this.showForm = gui.showForm
    this.lockUnlockLayer = function(props){
        props = props || {}
        var tmp = {}
        if (props.matrix) {
            for (var key in props.matrix) {
                var item = props.matrix[key]
                tmp[key] = {
                    row : item.row,
                    name : item.name
                }
            }
        }
        return gui.lockUnlockLayer({
            title: props.title || "lockUnlockLayer",
            layermatrix:props.layermatrix || tmp 
        })
    } 
    this.passwordBox = function(props){
        props = props || {}
        return gui.passwordBox({title:props.title || "password", password:props.password || "1212"})
    } 
    this.selectJobLayer = function (props) {
        props = props || {}
        return gui.selectJobLayer({
            layertypelist: props.layertypelist || [
                {name: "all", display_name: "all", filter: function(x) { return x }},
                {name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
                {name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
                {name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
                {name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
                {name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
                {name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
                {name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
                {name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
                {name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
            ],
            //defaultlayertype: "ha",
            joblist: props.joblist || [],
            defaultJob: props.defaultJob || [], // select by default
            steplist: props.steplist || [],
            // defaultstep: "step3",
            showstep: props.showstep || true,
            selectmode: props.selectmode || "multiple", // single/multiple
            layermatrix: props.layermatrix || {  },
            defaultlayer: props.defaultlayer || []
        })
    }
}

function getLayer(props){
    if(!props){return}
    if(!props.context){props.context = "board"}
    var matrix = GEN.getMatrix({job:job})
    return Object.keys(matrix).reduce(function(a,b){
        var info = matrix[b];
        var ret = true;
        for (var key in props) { if(!Array.isArray(props[key])){props[key] = [props[key]]}
        if(info[key] && props[key].indexOf(info[key]) < 0){ ret = false } }
        if(ret){  a.push(props.res == "info"? info : b) } return a
    },[])
}


function _deleteLayer(layers){
	layers = Array.isArray(layers.layer) ? layers.layer : [layers.layer];
	layers.forEach(function(layer){
		if(GEN.isLayerExists({job:Job,layer:layer})){
			GEN.deleteLayer({job:Job,layer:[layer]})
		}
	})
}

function getWorkStep(props){
	var steplists = GEN.getStepList({job:job});
	if(steplists.length == 0){return "该料号没有step"}
	var steps_tmp = steplists.filter(function(name){
		var reg = new RegExp(par.step_filter, "ig")
		return reg.test(name)
	})
	if(steplists.length == 0){return "根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!"}
	var workstep = gui.selectMultiple({
		title: "请先择工作step",
		size:[200,100],
		defaultsize:[200,100],
		list: steplists.map(function(v){ var tmp = {}; tmp[v] = v ;return tmp}),
		defaultvalue: steps_tmp,
		columns: 1,
		gen: GEN
	})
	if(workstep.length == 0 ) {return "没有先择step"}
	return workstep
}

function select_work_layer(par) {
	var drill = [];
	var matrix = GEN.getMatrix({job:Job});
	Object.keys(matrix).forEach(function(layer){
		if (!/ddr/.test(layer)){
			if(matrix[layer].layer_type == "drill"){
				drill.push(layer)
			}
		}
	})
	if(drill.length == 0){
		IKM.msg("资料中未找到钻孔层")
	}
	if (PAR.is_select_lyr == 'yes' && drill.length > 1) {
		var tmp_matrix={};
		drill.forEach(function(v){
			tmp_matrix[v] = matrix[v]
		})
		drill = GUI.selectLayer({
			title:'请选择输出层别',
			layermatrix:tmp_matrix,
			selectmode : 'multiple'}); // single
	}
	return drill;
}


function get_scale_info(par){
	var rows={},n=0;
	par.layers.forEach(function(layer){
		n++;
		if(!rows[layer]){rows[layer] = {}}
		rows[layer].sequence   = n;
		rows[layer].layer      = layer;
		if(layer == "md"){
			rows[layer].x = 1.0004;
			rows[layer].y = 1.0004;
		}
		else{
			rows[layer].x = 1.0000;
			rows[layer].y = 1.0000;			
		}
	})
	return rows;
}

function drill_out(par){
	var nc_set = par.layer;
	var ncsets = GEN.getNcsetsList({job:Job,step:Step,layer:par.layer});
	if( ncsets.length ){
		if (ncsets.filter(function(v){return /^($nc_set)$/.test(v)}).length > 0) {
			GEN.COM('ncset_delete',{name:nc_set});
		}
	}
	//钻带涨缩中心点
	var anchor_x = (par.scale_x != 1 || par.scale_y != 1) ? PAR.profile_limits.xc : 0;
	var anchor_y = (par.scale_x != 1 || par.scale_y != 1) ? PAR.profile_limits.yc : 0;
	
	if(fs.exists(PAR.out_dir+"/"+par.output_layer)){
		fs.unlink(PAR.out_dir+"/"+par.output_layer)
	}

	var org_x=0,org_y=0,angle;
	// if(PAR.profile_limits.ysize == 603 && PAR.profile_limits.xsize == 706){
	// 	org_x = PAR.profile_limits.yc;//- 15
	// 	org_y = 5;
	// 	angle = 270;
	// }else if(PAR.profile_limits.ysize == 603 && PAR.profile_limits.xsize == 606){
	// 	org_x = PAR.profile_limits.xc;//- 5
	// 	org_y = 5;
	// 	angle = 0;
	// }else{
	// 	org_x = PAR.profile_limits.xc;//- 24
	// 	org_y = 5;
	// 	angle = 0;
	// }
	
	// 导出	
	GEN.COM("ncset_cur,job="+Job+",step="+Step+",layer="+par.layer+",ncset="+nc_set);
    GEN.COM("ncd_set_machine,machine=excellon2,thickness=0");//excellon2 cpc_pn basic_excellon
	GEN.COM("ncd_register,angle=0,mirror=no,xoff=0,yoff=0,version=1,xorigin="+org_x+
	",yorigin="+org_y+",xscale="+par.scale_x+",yscale="+par.scale_y+
	",xscale_o="+anchor_x+",yscale_o="+anchor_y);
	GEN.COM("ncd_cre_drill");
    GEN.COM("ncd_ncf_export,stage=1,split=1,dir="+PAR.out_dir+",name="+par.output_layer);
	GEN.COM("ncset_delete,name="+par.layer);
}


// 整理输出文件数据
function edit_nc_file(par){
	// {
	// 	"layer": "drl",
	// 	"output_file": "C:/Users/Administrator/Desktop/jobs/demo/new_test/demo-drl-ori",
	// 	"new_file": "C:/Users/Administrator/Desktop/jobs/demo/new_test/new_test.drl",
	// 	"x": 1,
	// 	"y": 1
	// }
	// 读取文件内容
	var fileCtx = fs.readFile(par.output_file);
	// 分割文件内容
	var data = split_program(fileCtx);
	// 排序 
	convert_new_program(data);
	// 重写
	write_new_file({new_file:par.new_file, data:data})
}

// 分割文件内容
function split_program(string){
	var data = string.split("\n");
	var info = {overhead:[],head:[],neck:[],body:[],end:[]};
	var flag="start",router_flag;

	data.forEach(function(line){
		if( flag == 'start' ){
			if( line == 'M48' ){
				flag = 'overhead';
			}
		}
		else if( flag == 'overhead' ){
			if( /^T01C/i.test(line) ){
				flag = 'head';
			}
		}
		else if( flag == 'head' ){
			if( !/^T\d+/i.test(line) ){
				flag = 'neck';
			}
		}
		else if( flag == 'neck' ){
			if( /^T01/i.test(line) ){
				flag = 'body';
			}
		}
		else if( flag == 'body' ){
			if( /^M30$/i.test(line) ){
				flag = 'end';
			}
		}
		if( flag == 'overhead' ){
			info.overhead.push(line)
		}
		else if( flag == 'head' ){
			info.head.push(line)
		}
		else if( flag == 'neck' ){
			info.neck.push(line)
		}
		else if( flag == 'body' ){
			if(/^(T(\d+))$/i.test(line) ){
				router_flag = RegExp.$1;
			}
			if(router_flag){
				if(!/^T\d/.test(line)){
					var tmpT = info.body.filter(function(v){
						return v.name == router_flag
					})
					if(tmpT.length > 0){
						tmpT[0].value.push(line)
					} else {
						info.body.push({
							name: router_flag,
							value: [line]
						})
					}
				}
				//判断孔的范围 2020-04-21
				// if($num - $section_number < 0.001 and line !~ /^T/){
				// 	my $point = change_coode_to_vale(line);
				// 	my $are_check = 0;
				// 	foreach my $symbol (@drl_section_data){
				// 		my $dist = TL::GenMath->point2sym_dist($point,$symbol);
				// 		if($dist == 0){
				// 			$are_check = 1;
				// 			last;
				// 		}
				// 	}
				// 	if($are_check){
				// 		push @drl_section,line;
				// 	}else{
				// 		push @{$info{body}{$router_flag}{value}},line;
				// 	}
				// }else{
					// info.body[router_flag].value.push(line)
				// }
			}
		}
		else if( flag == 'end' ){
			info.end.push(line)
		}
	})
	return info
}


function convert_new_program(info){

	// 这里只对head和body排序
	var head = info.head;
	var body = info.body;

	// 做一个临时排序基准数组
	var head_tmp = head.map(function(v) {
		var tmp = v.split(/c/ig)
		return {
			name:tmp[0],
			value : parseFloat(tmp[1]) 
		}
	})

	head_tmp.sort(function(a,b){
		var a_tmp_value = (a.value==2.1 || a.value==0.7) ? -a.value : a.value;
		var b_tmp_value = (b.value==2.1 || b.value==0.7) ? -b.value : b.value;
		if(/\.\d\d1$/.test(a_tmp_value)){
			a_tmp_value = a_tmp_value + 10000;
		}
		if(/\.\d\d1$/.test(b_tmp_value)){
			b_tmp_value = b_tmp_value + 10000;
		}
		if(/\.\d\d2$/.test(a_tmp_value)){
			a_tmp_value = a_tmp_value + 20000;
		}
		if(/\.\d\d2$/.test(b_tmp_value)){
			b_tmp_value = b_tmp_value + 20000;
		}
		return a_tmp_value - b_tmp_value;
	})
	head_tmp = head_tmp.map(function(v){return v.name})

	// head  body  根据基准排序
	head.sort(function(a,b){
		var aT = /^(T\d+)C/.exec(a)[1];
		var bT = /^(T\d+)C/.exec(b)[1];
		return head_tmp.indexOf(aT) - head_tmp.indexOf(bT)
	})
	body.sort(function(a,b){
		var aT = a.name;
		var bT = b.name;
		return head_tmp.indexOf(aT) - head_tmp.indexOf(bT)
	})

	// 重写head与body
	head = head.map(function(v, i){
		var Tnum = /^T(\d+)C/.exec(v)[1] - 0;
		if(Tnum != (i+1)){
			var newT = "T" + ((i+1)>9? (i+1) : "0"+(i+1))
			v = v.replace(/^T\d+/, newT)
		}
		return v
	})
	body = body.map(function(v, i){
		var Tnum = /^T(\d+)/.exec(v.name)[1] - 0;
		if(Tnum != (i+1)){
			var newT = "T" + ((i+1)>9? (i+1) : "0"+(i+1))
			v.name = newT
		}
		return v
	})
	info.head = head;
	info.body = body;
}


function write_new_file(par){
	// {new_file:new_file, data:data}
	var data = par.data
	var newstr = "";
	var overhead = data.overhead.join("\n");
	var neck = data.neck.join("\n");
	var head = data.head.join("\n");

	newstr += overhead + "\n" + head + "\n" + neck + "\n";

	var body = "";
	data.body.forEach(function(v){
		body += v.name + "\n";
		body += v.value.join("\n") + "\n"
	})
	newstr += body;

	var end = data.end.join("\n");
	newstr += end;
	fs.writeFile(par.new_file, newstr)
}

function input_drill_program(par){
	GEN.COM( "input_manual_reset");
	GEN.COM( "input_manual_set,path="+par.file+",job="+Job+",step="+Step
	+",format=Excellon2,data_type=ascii,units=mm,coordinates=absolute,"
	+"zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer="+par.new_layer
	+",wheel=,wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,"
	+"signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
	GEN.COM( "input_manual,script_path=");
	GEN.zoomHome();
}