=head
 NAME: 
 DESCRIPTION: Signal线路掏铜
 PARAMETER:
	[
		{
			name : 'step_filter',
			type : 'LineEdit',
			title : 'step过滤',
			pack : {row:0,column:1},
			property:{tool_tip:'选择step时候的过滤器'},
		},
		{
			name : 'opt_item',
			title : '优化类型',
			type : 'ComboBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'inner',text:'内层'},
					{name:'outer',text:'外层'},
				]
			},
		},
		{
			name : 'drl_layer',
			type : 'LineEdit',
			title : '钻孔层',
			pack : {row:0,column:1},
			property:{tool_tip:'钻孔层'},
		},
		{
			name : 'outline_layer',
			type : 'LineEdit',
			title : '外形层',
			pack : {row:0,column:1},
			property:{tool_tip:'外形层'},
		},
		{
			name : 'ignore_attributes',
			type : 'LineEdit',
			title : '忽略的铜皮属性',
			pack : {row:0,column:1},
			property:{tool_tip:'忽略的铜皮属性'},
		},
		{
			name : 'fill_data',
			type : 'LineEdit',
			title : '去铜丝参数',
			pack : {row:0,column:1},
			property:{tool_tip:'去铜丝参数'},
		},
		{
			name : 'shave_cu_rule',
			title : '削铜参数规则',
			type : 'CodeEdit',
			property : {min_row_count: 5, tool_tip : ''},
		},
		{
			name : 'bak_layer_suf',
			type : 'LineEdit',
			title : '备份层后缀',
			pack : {row:0,column:1},
			property:{tool_tip:'去铜丝参数'},
		}
	]
 VERSION_HISTORY:
	V1.00 2020-10-30 Super
	   1.新版
	V1.01 2020-11-5 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->{fill_data} = $PAR->{fill_data} ? $PAR->{fill_data} : 1;
$PAR->{bak_layer_suf} = $PAR->{bak_layer_suf} ? $PAR->{bak_layer_suf} : '++--bak++';

try {
	unless($PAR->{drl_layer}){
		$GUI->msgbox(-icon=>'error',-text=>"请先设置钻孔层参数!");
        return 'Error';
	}
	unless($PAR->{outline_layer}){
		$GUI->msgbox(-icon=>'error',-text=>"请先设置外形层参数!");
        return 'Error';
	}
	unless($PAR->{opt_item}){
		$GUI->msgbox(-icon=>'error',-text=>"请先设置优化类型!");
        return 'Error';
	}
	###检查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');
	@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();

	update_loading("确认削铜参数...",0,position=>'n');
	my $file = $GEN->getJobPath(job=>$Job).'/user/'.'shave_cu_info';
	my (%rows,$n);
	foreach my $layer (@work_layers){
		$n++;
		$rows{$layer}{sequence} = $n;
		$rows{$layer}{layer} = $layer;
		$rows{$layer}{cu} = '';
		$rows{$layer}{pad_cu} = 0;
		$rows{$layer}{line_cu} = 0;
		$rows{$layer}{smd_cu} = 0;
		$rows{$layer}{bga_cu} = 0;
		$rows{$layer}{np_cu} = 0;
		$rows{$layer}{drl_cu} = 0;
		$rows{$layer}{cu_cu} = 0;
		$rows{$layer}{outline_cu} = 0;
	}
	my $ShowForm = $GUI->show_tableform (
			-title=>'请确认参数',
			-defaultsize=>[900,500],
			-rows => \%rows,
			-showcheck => 1,-gen => $GEN,
			-buttons=>[
				{
					response=>'help',
					stock=>'载入上次填入值',
					command=>sub{
					my %par = @_;
					$par{formpanel}->load_data(do($file)) if -f $file;
					}
				},
				{response=>'ok',stock=>'gtk-ok'},
				{response=>'cancel',stock=>'gtk-cancel'},
			],
			-columns => [
				{
					column_name=>'layer',
					label=>'层名称',
					width=>70,
					type=>'label',
				},
				{
					column_name=>'cu',
					label=>'铜箔厚度',
					type=>'enum',
					width=>70,
					must_field=>1,
					property=>{
						tl_field=>[name=>'scalar',display_name=>'text'],
						tl_value_field=>'name',
						tl_data=>[
							{name=>'1/4',display_name=>'1/4oz'},
							{name=>'1/3',display_name=>'1/3oz'},
							{name=>'1/2',display_name=>'1/2oz'},
							{name=>'1',display_name=>'1oz'},
							{name=>'1.5',display_name=>'1.5oz'},
							{name=>'2',display_name=>'2oz'},
						]
					},
					validate_func=>sub{
						my %par = @_;
						my $cu = $par{formpanel}->get_value($par{row},'cu');
						my ($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu);
						unless($PAR->{shave_cu_rule}){
							($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu) =   (0,0,0,0,0,0,0,0);
						}else{
							($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu) = eval($PAR->{shave_cu_rule})->($cu);
						}
						$par{formpanel}->set_value($par{row},'pad_cu',$pad_cu) if ( $par{mode} eq 'keyin' );
						$par{formpanel}->set_value($par{row},'line_cu',$line_cu) if ( $par{mode} eq 'keyin' );
						$par{formpanel}->set_value($par{row},'smd_cu',$smd_cu) if ( $par{mode} eq 'keyin' );
						$par{formpanel}->set_value($par{row},'bga_cu',$bga_cu) if ( $par{mode} eq 'keyin' );
						$par{formpanel}->set_value($par{row},'drl_cu',$drl_cu) if ( $par{mode} eq 'keyin' );
						$par{formpanel}->set_value($par{row},'np_cu',$np_cu) if ( $par{mode} eq 'keyin' );
						$par{formpanel}->set_value($par{row},'cu_cu',$cu_cu) if ( $par{mode} eq 'keyin' );
						$par{formpanel}->set_value($par{row},'outline_cu',$outline_cu) if ( $par{mode} eq 'keyin' );
						return {};
					}
				},
				{
					column_name=>'pad_cu',
					label=>'PAD到铜',
					width=>80,
					type=>'number',
					units=>'mil',
				},
				{
					column_name=>'line_cu',
					label=>'线到铜',
					width=>80,
					type=>'number',
					units=>'mil',
				},
				{
					column_name=>'smd_cu',
					label=>'SMD到铜',
					width=>80,
					type=>'number',
					units=>'mil',
					validate_func=>sub{
						my %par = @_;
						my $layer = $par{formpanel}->get_value($par{row},'layer');
						if($matrix{$layer}{tl_type} eq 'inner'){
							$par{formpanel}->set_value($par{row},'smd_cu',0)unless( $par{mode} eq 'save' );
							$par{formpanel}->get_widget($par{row},'smd_cu')->set_sensitive(0);
						}
						return {};
					}
				},
				{
					column_name=>'bga_cu',
					label=>'BGA到铜',
					width=>80,
					type=>'number',
					units=>'mil',
					validate_func=>sub{
						my %par = @_;
						my $layer = $par{formpanel}->get_value($par{row},'layer');
						if($matrix{$layer}{tl_type} eq 'inner'){
							$par{formpanel}->set_value($par{row},'bga_cu',0)unless( $par{mode} eq 'save' );
							$par{formpanel}->get_widget($par{row},'bga_cu')->set_sensitive(0);
						}
						return {};
					}
				},
				{
					column_name=>'drl_cu',
					label=>'孔到铜',
					width=>80,
					type=>'number',
					units=>'mil',
					validate_func=>sub{
						my %par = @_;
						my $layer = $par{formpanel}->get_value($par{row},'layer');
						if($matrix{$layer}{tl_type} eq 'outer'){
							$par{formpanel}->set_value($par{row},'drl_cu',0)unless( $par{mode} eq 'save' );
							$par{formpanel}->get_widget($par{row},'drl_cu')->set_sensitive(0);
						}
						return {};
					}
				},
				{
					column_name=>'np_cu',
					label=>'NP孔到铜',
					width=>80,
					type=>'number',
					units=>'mil',
				},
				{
					column_name=>'cu_cu',
					label=>'铜到铜',
					width=>80,
					type=>'number',
					units=>'mil',
				},
				{
					column_name=>'outline_cu',
					label=>'外形到铜',
					width=>90,
					type=>'number',
					units=>'mil',
				},
			]
	);
	return 'Cancel' unless $ShowForm;
	open(my $fh,'>',$file); print $fh dump($ShowForm); close $fh;
	
	$GEN->COM("disp_off");
	foreach my $layer (@work_layers){
		my @del_layers;
		$GEN->affectedLayer(affected=>'yes',layer=>$layer,clear_before=>'yes');
		$GEN->selectByFilter(polarity=>'negative',profile=>'all');
		if ( $GEN->getSelectCount() > 0 ){
			$GEN->COM('sel_clear_feat');
			$GUI->msgbox(-icon=>'error',-text=>$layer.'层资料中有负片,请先处理好!');
			return 'Error';
		}
		my $bak_layer = $layer.($PAR->{bak_layer_suf});
		#备份
		$GEN->createLayer(job=>$Job,layer=>$bak_layer,context=>'misc',type=>'document',delete_exists=>'yes');
		$GEN->selCopyOther(target_layer=>$bak_layer,invert=>'no');
		#铜皮层
		my $cu_tmp_layer = $layer.'+-+tmp+cu++';
		$GEN->createLayer(job=>$Job,layer=>$cu_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
		$GEN->selectByFilter(feat_types=>'surface',polarity=>'positive',profile=>'all');
		if(defined($PAR->{ignore_attributes})){
			$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>$PAR->{ignore_attributes}}],operation=>'unselect');
		}
		if ( $GEN->getSelectCount() > 0 ){
			$GEN->selMoveOther(target_layer=>$cu_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0);
			push @del_layers,$cu_tmp_layer;
		}else{
			next;
		}
		#SMD层
		my $smd_tmp_layer = $layer.'+-+tmp+smd++';
		if($ShowForm->{$layer}{smd_cu} > 0){
			$GEN->createLayer(job=>$Job,layer=>$smd_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
			$GEN->selectByFilter(feat_types=>'pad',attribute=>[{attribute=>'.smd'}],polarity=>'positive',profile=>'all');
			$GEN->selectByFilter(attribute=>[{attribute=>'.bga'}],operation=>'unselect');
			$GEN->selMoveOther(target_layer=>$smd_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 );
			push @del_layers,$smd_tmp_layer;
		}
		#BGA层
		my $bga_tmp_layer = $layer.'+-+tmp+bga++';
		if($ShowForm->{$layer}{bga_cu} > 0){
			$GEN->createLayer(job=>$Job,layer=>$bga_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
			$GEN->selectByFilter(feat_types=>'pad',attribute=>[{attribute=>'.bga'}],polarity=>'positive',profile=>'all');
			$GEN->selMoveOther(target_layer=>$bga_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 );
			push @del_layers,$bga_tmp_layer;
		}
		#PAD层
		my $pad_tmp_layer = $layer.'+-+tmp+pad++';
		if($ShowForm->{$layer}{pad_cu} > 0){
			$GEN->createLayer(job=>$Job,layer=>$pad_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
			$GEN->selectByFilter(feat_types=>'pad',polarity=>'positive',profile=>'all');
			$GEN->selMoveOther(target_layer=>$pad_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 );
			push @del_layers,$pad_tmp_layer;
		}
		#line层
		my $line_tmp_layer = $layer.'+-+tmp+line++';
		if($ShowForm->{$layer}{line_cu} > 0){
			$GEN->createLayer(job=>$Job,layer=>$line_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
			$GEN->selectByFilter(feat_types=>'line\;arc',polarity=>'positive',profile=>'all');
			$GEN->selMoveOther(target_layer=>$line_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 );
			push @del_layers,$line_tmp_layer;
		}
		#掏铜
		my %feat_hist = $GEN->getLayerFeatHist(job=>$Job,step=>$Step,layer=>$cu_tmp_layer);
		my $tmp_layer = 'tl++tmp+cu+++';
		$GEN->createLayer(job=>$Job,layer=>$tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
		for(my $index = 1;$index <= $feat_hist{total};$index++){
			update_loading('一共'.($feat_hist{total}).'铜皮'.' '.'第'.$index.'块优化中...',0,position=>'n');
			$GEN->affectedLayer(affected=>'yes',layer=>$cu_tmp_layer,clear_before=>'yes');
			$GEN->COM('sel_layer_feat',operation=>'select',layer=>$cu_tmp_layer,index=>$index);
			$GEN->selMoveOther(target_layer=>$tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0);
			if($ShowForm->{$layer}{smd_cu} > 0){
				$GEN->affectedLayer(affected=>'yes',layer=>$smd_tmp_layer,clear_before=>'yes');
				$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
				$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{smd_cu}) if ( $GEN->getSelectCount() > 0 );
			}
			if($ShowForm->{$layer}{bga_cu} > 0){
				$GEN->affectedLayer(affected=>'yes',layer=>$bga_tmp_layer,clear_before=>'yes');
				$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
				$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{bga_cu}) if ( $GEN->getSelectCount() > 0 );
			}
			if($ShowForm->{$layer}{pad_cu} > 0){
				$GEN->affectedLayer(affected=>'yes',layer=>$pad_tmp_layer,clear_before=>'yes');
				$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
				$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{pad_cu}) if ( $GEN->getSelectCount() > 0 );
			}
			if($ShowForm->{$layer}{line_cu} > 0){
				$GEN->affectedLayer(affected=>'yes',layer=>$line_tmp_layer,clear_before=>'yes');
				$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
				$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{line_cu}) if ( $GEN->getSelectCount() > 0 );
			}
			#NP孔到铜
			$GEN->affectedLayer(affected=>'yes',layer=>$PAR->{drl_layer},clear_before=>'yes');
			$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'non_plated'}]);
			$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{np_cu}) if ( $GEN->getSelectCount() > 0 );
			if($ShowForm->{$layer}{drl_cu} > 0){
				$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
				$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{drl_cu}) if ( $GEN->getSelectCount() > 0 );
			}
			#外形到铜
			$GEN->affectedLayer(affected=>'yes',layer=>$PAR->{outline_cu},clear_before=>'yes');
			$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{outline_cu}) if ( $GEN->getSelectCount() > 0 );
			#铜到铜
			$GEN->affectedLayer(affected=>'yes',layer=>$cu_tmp_layer,clear_before=>'yes');
			$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
			$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>$ShowForm->{$layer}{cu_cu}) if ( $GEN->getSelectCount() > 0 );
			#转铜,除细丝
			$GEN->affectedLayer(affected=>'yes',layer=>$tmp_layer,clear_before=>'yes');
			$GEN->selContourize();
			if($PAR->{fill_data}){
				$GEN->selFill(solid_type=>'fill',min_brush=>$PAR->{fill_data});
				$GEN->selContourize();
			}
			$GEN->selMoveOther(target_layer=>$layer,invert=>'no',dx=>0,dy=>0,size=>0);
			$GEN->deleteLayer(job=>$Job,layer=>$tmp_layer);
		}
		#与铜皮相连的PAD处理


		#补铜桥部分


		#物件还原
		foreach my $tmp (@del_layers){
			if($GEN->isLayerExists(job=>$Job,layer=>$tmp) and ! $GEN->isLayerEmpty(job=>$Job,step=>$Step,layer=>$tmp)){
				$GEN->affectedLayer(affected=>'yes',layer=>$tmp,clear_before=>'yes');
				$GEN->selMoveOther(target_layer=>$layer,invert=>'no',dx=>0,dy=>0,size=>0);
			}
			$GEN->deleteLayer(job=>$Job,layer=>$tmp);
		}
	}

    ###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->clearLayers();
	$GEN->affectedLayer( mode=>'all',affected=>'no' );
	$GEN->COM("disp_on");
};

sub isChecklistExist{
    my %par = @_ ;
    my @chklists = $GEN->getChecklist(job=>$par{job},step=>$par{step});
    if(grep /^$par{checkklist}$/,@chklists){
        return 1;
    }
    else{
        return 0;
    }
}


=head
	选择线路层
=cut
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 'signal' and $matrix{$layer}{tl_type} eq $PAR->{opt_item}){
				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;
}



#掏铜参数
# sub{
# 	my $cu = shift;
# 	my $data;
# 	@{$data->{0.5}}=(1,2,3,4,5,1,6);
# 	@{$data->{1}}=(2,3,4,5,6,2,7);
# 	if(defined($data->{$cu})){
# 		return @{$data->{$cu}};
# 	}else{
# 		return (0,0,0,0,0,0);
# 	}
# }