=head
 NAME: 
 DESCRIPTION: 自动转PAD
 PARAMETER:
	[
		{
			name : 'step_filter',
			type : 'LineEdit',
			title : 'step过滤',
			pack : {row:0,column:1},
			property:{tool_tip:'选择step时候的过滤器'},
		},
		{
			name : 'max_pad_size',
			type : 'LineEdit',
			title : 'PAD最大尺寸(mil)',
			pack : {row:0,column:1},
			property:{tool_tip:'PAD最大尺寸(mil)'},
		},
		{
			name : 'tolerance',
			type : 'LineEdit',
			title : '公差(mil)',
			pack : {row:0,column:1},
			property:{tool_tip:'公差(mil)'},
		},
		{
			name : 'bak_layer_pad',
			type : 'LineEdit',
			title : '备份层后缀',
			pack : {row:0,column:1},
			property:{tool_tip:'去铜丝参数'},
		}
	]
 VERSION_HISTORY:
	V1.00 2020-10-12 Super
	   1.新版本
 HELP:
	<html><body bgcolor="#DDECFE">
		<font size="3" color="#003DB2"><p>功能简介</p></font>
		  <p> DFM优化 </p>
		  <br>
		<font size="3" color="#003DB2"><p>参数配置</p></font>
		<font color="#008000"><p> ● 无</p></font>
		<font size="3" color="#003DB2"><p>注意事项</p></font>
		  <p> ● 无 </p>
		  <br>
	</body></html>
  
=cut

use strict;
use utf8;
use Data::Dump 'dump';
my ($Job,$Step)=($JOB,undef);
my $Report = 'done';

my @work_layers;
$PAR->{max_pad_size} = $PAR->{max_pad_size} ? $PAR->{max_pad_size} : 500;
$PAR->{tolerance} = $PAR->{tolerance} ? $PAR->{tolerance} : 1;
$PAR->{bak_layer_pad} = $PAR->{bak_layer_pad} ? $PAR->{bak_layer_pad} : '++-bak-pad++';

try {
	###检查Genesis料号是否存在并打开
	show_loading("检查${Job}是否存在..",0,position=>'n');
	if (! $GEN->isJobExists(job=>$Job) ){
        $GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!");
        return 'Error';
    }

	update_loading("正在打开料号 ${Job} ...",0,position=>'n');
	$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
	my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');

	my @steps =  $GEN->getStepList(job=>$Job);
	if ( @steps == 0 ) {
		$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
		return 'Error';
	}
	elsif (@steps != 1){
		my $srep_filter = $PAR->{step_filter} ? $PAR->{step_filter} : '.*';
        my @tmp_steps = grep(/$srep_filter/,@steps);
		if ( @tmp_steps == 0 ) {
			$GUI->msgbox(-icon=>'error',-text=>'在料号中没有过滤器中的step存在,你将退出!');
			return 'Error';
		}
        elsif ( @tmp_steps == 1 ) {
            $Step = $tmp_steps[0];
        }
        else {
            $Step = $GUI->select_step(-title=>'请选择工作Step',
                                      -steplist=>\@tmp_steps,
                                      -selectmode=>'single');
            return 'Cancel' unless ($Step);            
        }
	}
    else {
        $Step = $steps[0];
    }

	##
	update_loading("过滤层别...",0,position=>'n');
	my @work_layers = get_work_layer();
	return 'Cancel' if grep /^Cancel$/,@work_layers;

	###打开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=>'inch');
	$GEN->zoomHome();
	
	#优化参数
	my $itm_info = {
						'ref'   => {action=>'valor_cleanup_ref_subst',erf=>'STD',params=>{pp_layer=>'.affected',pp_tol=>$PAR->{tolerance}}},
						'auto'  => {action=>'valor_cleanup_auto_subst',erf=>'STD'},
	};
	
	#冒泡排序一次优先转阻焊层
	for(my $i = 0; $i < @work_layers; $i++){
		for(my $k = 0; $k < @work_layers - $i; $k++){
			if ($matrix{$work_layers[$k]}{layer_type} ne 'solder_mask' and $matrix{$work_layers[$k+1]}{layer_type} eq 'solder_mask'){
				my $tmp = $work_layers[$k];
				$work_layers[$k] = $work_layers[$k+1];
				$work_layers[$k+1] = $tmp;
			}
		}
	}
	
	foreach my $layer (@work_layers) {
		#备份层
		my $bak_layer = $layer.$PAR->{bak_layer_pad};
		$GEN->createLayer(job=>$Job,layer=>$bak_layer,context=>'misc',type=>'document',delete_exists=>'yes');
		$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$layer,dest_layer=>$bak_layer,mode=>'replace',invert=>'no');
		#外层要参考阻焊层转PAD
		my $mask_tmp_layer;
		if($matrix{$layer}{tl_type} eq 'outer'){
			foreach my $lay (sort {$matrix{$a}{row} <=> $matrix{$b}{row}}  keys %matrix) {
				if($matrix{$lay}{tl_type} eq 'solder_mask' and $matrix{$lay}{side} eq $matrix{$layer}{side}){
					$mask_tmp_layer = $lay;
				}
			}
			if(defined($mask_tmp_layer)){
				$GEN->affectedLayer(affected=>'yes',layer=>$mask_tmp_layer,clear_before=>'yes');
				$GEN->selectByFilter(feat_types=>'line\;arc',min_len=>0.004,max_len=>$PAR->{max_pad_size}/1000,polarity=>'positive',profile=>'all');
				if($GEN->getSelectCount() > 0){
					$GEN->displayLayer(name=>$mask_tmp_layer,number=>1);
					$GUI->msgbox(-icon=>'info',-text=>"阻焊层 $mask_tmp_layer 中含有规则物件！会影响 $layer 层转PAD效果,请确认。。。");
					$GEN->PAUSE('Please,Check Layer Features!');
					$GEN->COM('sel_clear_feat');
				}
			}
		}

		$GEN->affectedLayer(affected=>'yes',layer=>$layer,clear_before=>'yes');
		if($matrix{$layer}{tl_type} eq 'outer'){
			$GEN->runSingleDfm(
								chklist => $itm_info->{auto}{action},
								erf     => $itm_info->{auto}{erf},
								show_res=> 'no',
								params  => {
											   pp_layer  =>'.affected',  	 pp_in_selected=>'All',
											   pp_min_smd=>0.001,		 	 pp_max_smd=>$PAR->{max_pad_size},
											   pp_tol	 =>$PAR->{tolerance},pp_ref_sm=>$mask_tmp_layer,
											   pp_auto_ref=>'Auto Ref.',	 pp_sm_margin=>0,
											   pp_drill_margin=>0,			 pp_work=>'Features',
											   pp_construct=>'No'
								}
			);
		}else{
			$GEN->runSingleDfm(
								chklist => $itm_info->{auto}{action},
								erf     => $itm_info->{auto}{erf},
								show_res=> 'no',
								params  => {
											   pp_layer  =>'.affected',  	 pp_in_selected=>'All',
											   pp_min_smd=>0.004,		 	 pp_max_smd=>$PAR->{max_pad_size},
											   pp_tol	 =>$PAR->{tolerance},pp_ref_sm=>'',
											   pp_auto_ref=>'',				 pp_sm_margin=>0,
											   pp_drill_margin=>0,			 pp_work=>'Features',
											   pp_construct=>'No',
								}
			);
		}

		#全部是PAD的时候不需要手动操作
		$GEN->selectByFilter(polarity=>'positive',profile=>'all');
		$GEN->selectByFilter(feat_types=>'pad',operation=>'unselect');
		next unless ($GEN->getSelectCount());
		$GEN->COM('sel_clear_feat');
		$GEN->workLayer(name=>$layer,display_number=>1,clear_before=>'yes');
		$GEN->highlightByFilter(feat_types=>'pad',polarity=>'positive',profile=>'all');
		update_loading("请仔细检查 $layer 当前PAD,框选需要转PAD的物件,无需转PAD时框选空白结束...",0,position=>'n');
		while(1){
			my %mouse_area = $GEN->MOUSE(type=>'r',text=>'Please Select The Construct Pad Feature');
			$GEN->selectRectangle(x1=>$mouse_area{x1},y1=>$mouse_area{y1},x2=>$mouse_area{x2},y2=>$mouse_area{y2});
			unless ($GEN->getSelectCount()){
				$GEN->clearHighlight();
				last ;
			}else{
				$GEN->runSingleDfm(
						chklist  => $itm_info->{ref}{action},
						erf      => $itm_info->{ref}{erf},
						params   => $itm_info->{ref}{params},
						show_res => 'no'
				);
				$GEN->clearHighlight();
				$GEN->highlightByFilter(feat_types=>'pad',polarity=>'positive',profile=>'all');
			}
		}
	}

    ###output and return status, if genesis error, it will output genesis error command
	unless ($GEN->{STATUS}){
		return $Report;
	}
	else{
		$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
		addFlowNotes(-notes=>"   Genesis Error:\n ".join("\n   ",@{$GEN->{STATUS}}));
		return 'Error';
	}
}

catch Error::Simple with {
	my $error = shift;
	$GUI->msgbox(-icon=>'error',-text=>$error);
	return 'Error';
}

finally{
	$GEN->affectedLayer( mode=>'all',affected=>'no');

};


sub get_work_layer{	
	# 获取工作层
	my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');
	foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}}  keys %matrix) {
		if(defined($matrix{$layer}{context}) and $matrix{$layer}{context} eq 'board' ){
			if(defined($matrix{$layer}{layer_type}) and ($matrix{$layer}{layer_type} eq 'solder_mask' or $matrix{$layer}{layer_type} eq 'signal')){
				push @work_layers,$layer;
			}
		}
	}
	##
	my %tmp_matrix;
	foreach my $layer (@work_layers) {
		$tmp_matrix{$layer} = $matrix{$layer};
	}	
	
	if (@work_layers > 1) {
		@work_layers = $GUI->select_layer(
			-title=>'请选择工作层别',
			-layermatrix=>\%tmp_matrix,
			-selectmode => 'multiple');#single
		return 'Cancel' unless(@work_layers);
	}
	else {
		@work_layers = @work_layers;
	}
	return @work_layers;
}