#!/usr/lib/perl
if (!(-e "/mnt/application/xml/clis/XMLInvalidTagConfig.txt")){
	exit;
}
open(INVALID,"+>/mnt/application/xml/clis/XMLInvalidCLIConfig.txt") or die "Can't create ignored CLIs File:$!";
open(DB1,"/bsn/newdb1") or die "Can't open main database File:$!";
open(DB2,"/bsn/newdb2") or die "Can't open supporting database File:$!";
open(DB3,"/bsn/newdb3") or die "Can't open value to string database File:$!";
open(DB5,"/bsn/newdb5") or die "Can't open format specifier database File:$!";
open(DB8,"/bsn/newdb8") or die "Can't open format specifier database File:$!";                   
open(INVDB,"/mnt/application/xml/clis/XMLInvalidTagConfig.txt") or die "Can't open invalid database File:$!";
open(IGNORED,"/mnt/application/xml/clis/XMLIgnoredCLIConfig.txt") or die "Can't create ignored CLIs File:$!";
my (%hash1, %hash2,%hash_xml, %hash3, %hash8);
my $k=0;
my $xml_file;

for $line(<DB1>){
#This database contains base cli to tag hierarchy mapping.
        chomp $line;
        @line=split('\t',$line,2);
        $hash1{$line[0]}=$line[1];
}

for $line(<DB2>) {
        chomp $line;
        @line=split('\t',$line,2);
        $hash2{$line[0]}=$line[1];
}

for $line(<DB3>){
        chomp $line;
        @line=split('\t',$line,2);
        $hash3{$line[0]}=$line[1];
	}
for $line(<DB8>){
        chomp $line;
        @line=split('\t',$line,3);
	if (!(defined $hash8{$line[0]}{0})) {
		$hash8{$line[0]}{0}=$line[1];
		next;
	}
	if (!(defined $hash8{$line[0]}{1})) {
		$hash8{$line[0]}{1}=$line[1];
		next;
	}
	if (!(defined $hash8{$line[0]}{2})) {
		$hash8{$line[0]}{2}=$line[1];
		next;
	}
	if (!(defined $hash8{$line[0]}{3})) {
		$hash8{$line[0]}{3}=$line[1];
		next;
}
}
generate_xml_filename_dbase();
initialise_interface();
invalid_clis();
append_ignored_config();

sub invalid_clis
{
	my ($tag_str,$tag_num,$last_tag);
	my ($line, $index);
        for $line(<INVDB>) {
                chomp $line;
		($line, $index)=split('\t', $line, 2);
		$last_tag = wrapper_for_name_to_digitdot($line);
		#Here index contains multiple index.
       		&search_for_cli($last_tag, $index);
        }
}                                                                                                                
#This subroutines searches number string and finds base cli.
sub search_for_cli
{
        my ($last_tag, $index)=@_;
        my ($tag_str,$val,$val_new,$invalidcli);
	my @clis_with_keyword;
	my $line = search_base_cli($last_tag, $index);
#print "$line  search_base_cli($last_tag, $index)\n";
                	@clis_with_keyword=split('\t',$line);
        my $i=1;
	#clis_with_keyword[0] contains base cli so start with index 1.
                        while($i<=$#clis_with_keyword) {
		my ($t1, $t2) = split('\#', $clis_with_keyword[$i], 2);#added for split at actions
               	my @arr=split('(a|b|c|d|e|f|g|h|i|j)', $t1);#split needed due to index identifiers.
               	$val=get_valid_tag_value($arr[0], $index) ;
		#print "The value for $clis_with_keyword[$i] with index $index is not present in $xml_filename\n"if (!defined ($val));
		return if (!defined ($val));
		$val_new = $val if ($last_tag eq $arr[0]);
				$clis_with_keyword[$i] = $val;
				$i++;
                        }
                        $invalidcli=join(' ',@clis_with_keyword);
	                print INVALID "$invalidcli\n";
	invalid_value_pointer($invalidcli,$val_new);
			close XML;
}

sub get_valid_tag_value
{
        my ($num_str, $index)=@_;
	my ($temp_line,$check_str,$local_str,$value, $num, $line);
	my @multi_index = split('\t', $index);
	my $idx = 0;
	my @individual_num=split('\.',$num_str);
	$tag_str=&num_to_str($num_str);
	$xml_filename=$hash_xml{$individual_num[0]};
	open(XML,"/mnt/application/xml/$xml_filename") or die "Can't open xml File:$!";
	$line=<XML>;
	while ($temp_line=<XML>) {
		my $num;
		$line=$temp_line;
		$line =~ tr/[<,>]/[ , ] /;
		$line =~ s/\s+//;
		@keyword=split(/\s/,$line);
                if (($keyword[1]) && ($keyword[1]=~/index/)){
 	               if ($keyword[1]=~/(\d+)/){
        		       $num=$1;
                	}
                }
		if (!($line =~ /\//))  {
                	if (($keyword[1]) && ($keyword[1]=~/index/)) {
				$idx-- if(!defined ($multi_index[$idx]));
				if ($num == $multi_index[$idx]) {
					$check_str.=$keyword[0]."." ;
					$idx++;
				}
				else {
					while (!($line =~ /\/$keyword[0]/)) {#Skipping the whole index array.
						$line=<XML>;
					}
				}
			}
			else {
				$check_str.=$keyword[0].".";	
			}
		}
		else {
			if (!defined($keyword[1])) {
				@check_str=split('\.',$check_str);
				$last_tag=pop (@check_str);
				$check_str=join('.',@check_str);
				$check_str.=".";
			}
			$local_str=$check_str.$keyword[0];
			if ($local_str eq $tag_str) {
				$value=$keyword[1];
				if (defined $hash3{$num_str}) {
				    if (!(string_to_num_bit_check($num_str,\$value))) {
	                               	print "Error:No string to value mapping found for $value in DB3.\n";
        	                        return ;
			}
		}
				last;
	}
		}#end else loop
	}#end while loop
        return $value;
}                                                                                    

sub invalid_value_pointer 
{
	my ($line,$value)=@_;
	$line=~ s/$value/\^/;
   	my @new_line=split(/\^/,$line,2);
	my $i=0;
	while($i<length($new_line[0])) {
        	print INVALID " ";
        	$i++;
	}
	print INVALID "^\n";
}

sub num_to_str
{
	my ($num_str)=@_;
	my @individual_num=split('\.',$num_str);
        my $string=$individual_num[0];
        my ($tag_str, $index_info) = split('\t', $hash2{$string});
        for (my $i=1;$i<=$#individual_num;$i++) {
                @num=split(' ',$individual_num[$i]);#Added to remove trailing space
                $string.=".".$num[0];
		my ($local_tag_str, $index_info) = split('\t', $hash2{$string});
                $tag_str.=".".$local_tag_str;
        }
	return $tag_str;
}

sub wrapper_for_name_to_digitdot
{
#Here input is whole tag hierarchy and we return the digit dot for last node.
    my ($tag_name) = @_;
    my $child_digitdot;
    my @tag_indvd_names = split('\.', $tag_name);
    my @parent_digitdot = search_for_tag($tag_indvd_names[0]);
    for (my $i = 1; $i <= $#tag_indvd_names; $i++) {
        my @tag_digitdot = search_for_tag($tag_indvd_names[$i]);
        foreach (@tag_digitdot) {
            $child_digitdot = parent_check ($_, $parent_digitdot[$i-1]);
            if ($child_digitdot ne "FALSE") {
                $parent_digitdot[$i] = $child_digitdot;
                last;
                        	}
                	}
        	}
     return $child_digitdot;
	}
                                                                                                              
sub parent_check
{
    my ($tag_str, $parent_str) = @_;
    if ($tag_str =~ /^$parent_str/ ) {
        return $tag_str;
    }
    else {
        return "FALSE";
    }
}
sub search_for_tag
{
        my ($tag_str)=@_;
        my @tag_num;
	my ($tag_name, $index_info);
        for (keys %hash2){
               ($tag_name, $index_info) = split('\t', $hash2{$_});
               push @tag_num,$_ if $tag_name eq $tag_str;
        }
        if (!defined (@tag_num)) {
                print "The $tag_str don't have any digitdot mapping defined in DB2\n";
        }
        return @tag_num;
}

sub search_base_cli
{
    my ($tag_string_to_search, $index) = @_;
    my $count =0;
    $index =0 if (!(defined $index));
    if (defined($hash8{$tag_string_to_search}{$index})) {
         $base_cli = $hash8{$tag_string_to_search}{$index}; 
    } else {
        $base_cli = $hash8{$tag_string_to_search}{0};
    } 
    $base_cli =~ s/<index>//;
    $base_cli =~ s/$tag_string_to_search//;
    $base_cli =~ s/[ ]*$//g;
    $base_cli = $base_cli."\t".$hash1{$base_cli};
    return $base_cli;
}

sub string_to_num_bit_check
{
         my ($tag_str,$value)=@_;
         my ($tmpval,@split_stv,@split_lv,$bit_val);
         my $str_to_val=$hash3{$tag_str};
         if(defined($str_to_val)){
                @split_stv=split('\t',$str_to_val);
                foreach(@split_stv){
                        my $local_var=$_;
                        @split_lv=split('=',$local_var);
                        if($split_lv[1] eq $$value){
                                $tmpval=$split_lv[0];
                                last;
	}
                        }
                        if (defined ($tmpval)) {
                                $$value = $tmpval;
                                return 1;
                        } else {
                                return 0;
                        }
        } else {
	return 0;
}
}

sub initialise_interface
{
    my @digitdot = search_for_tag('vlanLocalAddress');
    $hash8{$digitdot[0]}{0}= "config interface address management $digitidot[0]";
    $hash8{$digitdot[0]}{1}= "config interface address service-port $digitidot[0]";
    $hash8{$digitdot[0]}{2}= "config interface address virtual $digitidot[0]";
    $hash8{$digitdot[0]}{3}= "config interface address ap-manager $digitidot[0]";
    $hash8{$digitdot[0]}{4}= "config interface address dynamic-interface $digitidot[0]";
    my @digitdot = search_for_tag('vlanLocalNetmask');
    $hash8{$digitdot[0]}{0}= "config interface address management $digitidot[0]";
    $hash8{$digitdot[0]}{1}= "config interface address service-port $digitidot[0]";
    $hash8{$digitdot[0]}{3}= "config interface address ap-manager $digitidot[0]";
    $hash8{$digitdot[0]}{4}= "config interface address dynamic-interface $digitidot[0]";
    my @digitdot = search_for_tag('vlanLocalGateway');
    $hash8{$digitdot[0]}{0}= "config interface address management $digitidot[0]";
    $hash8{$digitdot[0]}{3}= "config interface address ap-manager $digitidot[0]";
    $hash8{$digitdot[0]}{4}= "config interface address dynamic-interface $digitidot[0]";
    my @digitdot = search_for_tag('vlanId');
    $hash8{$digitdot[0]}{0}= "config interface vlan management $digitidot[0]";
    $hash8{$digitdot[0]}{1}= "config interface vlan $digitidot[0]";
}
sub generate_xml_filename_dbase
{
    for my $line(<DB5>) {
        chomp $line;
        @line = split('\t',$line,2);
        $hash_xml{$line[0]}=$line[1];     
    }
}

system ("chmod 777 /mnt/application/xml/clis/XMLInvalidCLIConfig.txt");
if (!(-s "/mnt/application/xml/clis/XMLInvalidCLIConfig.txt")){
	system("rm /mnt/application/xml/clis/XMLInvalidCLIConfig.txt");
}
sub append_ignored_config
{
    if (!(-s "ignored_clis")) {
        return ;
    }
    print INVALID "\tIgnored Config\n";
    for my $line(<IGNORED>) {
        chomp $line;
        print INVALID "$line\n";
    }
}
                                                                                                  
close INVALID;
close IGNORED;
close INVDB;
close DB1;
close DB2;
close DB3;
close DB5;
close DB8;
