#!/usr/bin/perl

# $Id: //depot/cad/tools/1.0/icp4/bin/p4ci#8 $
#
# CSWITCH CORPORATION CONFIDENTIAL PROPRIETARY
# 
# This file contains information which is the
# proprietary property of Cswitch Corporation.
# This file is confidential and its contents may
# not be disclosed without the expressed written
# consent of Cswitch Corporation.


use strict;
use warnings;

use FindBin qw($Bin);
use lib "$Bin/../lib";

use Icp4;
use Getopt::Std;
use File::Basename;

our (%opt, $Program, $islayout);
our $attr_sfx = ".Ic_cell_template.attr";
our $cell_sfx = ".iccel_[0-9]+";
our $part_name     = "part";
our $part_attr_sfx = ".Eddm_part.attr";
our $part_cell_sfx = ".part_[0-9]+";

our $sm_attr_sfx   = ".mgc_symbol.attr";
our $sm_cell_sfx   = ".smbl_[0-9]+";

our $sch_name      = "sheet1";
our $sch_attr_sfx  = ".mgc_sheet.attr";
our $sch_cell_sfx  = ".(sgfx|ssht)_[0-9]+";

MAIN: {

    my ($cell, $orig_cell, $cmd, $cells);
    my ($attr_file, $orig_attr_file, $ic_pat);
    my ($openStat, $expectedStat, $orig_cnt, $del_cmd);
    my ($icfile, @allicfiles, @deletelist, $i);
    my (@keep_list);
    my ($part_attr, $part_pat);
    my ($sm_attr, $sm_pat);
    my ($sch_attr, $sch_pat);


    $Program = $FindBin::Script;

    getopts('hDnOrik:c:', \%opt);

    if ($opt{h} || $#ARGV < 0) {
	print "Usage: $Program [-h] [-n] [-r|-O|-c \"command\"] [-i] [-k num] cell+\n";
	print "   -h: help usage\n";
	print "   -n: show operation only\n";
	print "   -r: use unix remove instead of p4 delete\n";
	print "       (default: p4 delete)\n";
	print "   -O: use obliterate instead of p4 delete (requires p4 admin privileges)\n";
	print "       (default: p4 delete)\n";
	print "   -c: use custom command string instead of p4 delete\n";
	print "       (default: p4 delete)\n";
	print "   -i: ignore pending changes (dangerous!)\n";
	print "   -k: number of versions to keep\n";
	print "       (default: all files mentioned in the .attr file)\n";
	print " cell: cell name(s)\n";
	print "       (hint: use \\\$ for cells with \$ character in their name)\n";
	exit;
    }

    $Icp4::debug = ($opt{D}) ? 1 : 0 ;
    $Icp4::nflag = ($opt{n}) ? 1 : 0 ;

    $islayout = &Icp4::is_layout_view();

    # TODO: support schematics
#    if (! $islayout) {
#	print "INFO: $Program only works from the layout.views directory for now.  Exiting.\n";
#	exit -1;
#    }

    if (!$opt{i} && &Icp4::outstanding_changes()) {
	exit -1;
    }

    $cells = "";

    foreach $cell (@ARGV) {

	$orig_cell = $cell;

	# escape the name for p4
	if ($cell =~ /\$/) {
	    $cell =~ s/\$/\\\$/g;
	    print "# DEBUG: cell=$cell orig_cell=$orig_cell\n" if $opt{D};
	}

	if (-d $orig_cell) {
	    if ($islayout) {
		# remove any .iclck files
		unlink <$orig_cell/.*.iclck>;

		#$cell_attr = $cell . $attr_sfx;
		$ic_pat    = $cell . $cell_sfx;

		$orig_attr_file = "${orig_cell}/${orig_cell}${attr_sfx}";
		$attr_file = "${cell}/${cell}${attr_sfx}";

		if (! -f "$orig_attr_file") {
		    print "WARNING: $orig_attr_file not found.  Trying the .s trick.\n";
		    $orig_attr_file = "${orig_cell}/${orig_cell}.s${attr_sfx}";
		    $attr_file = "${cell}/${cell}.s${attr_sfx}";
		    if (! -f "$orig_attr_file") {
			print "WARNING: $orig_attr_file not found either.  Skipping \"$orig_cell\".\n";
			next;
		    } else {
			print "INFO: Found alternate $orig_attr_file.\n";
		    }
		}
		
		p4tidy_proc($orig_cell, $attr_file, $orig_attr_file, $ic_pat, 1);

	    } 
	    if (! $islayout)  {
		# part
		$part_attr = "$cell/$part_name" . $part_attr_sfx;
		$part_pat  = $part_name . $part_cell_sfx;
		if (-f "$part_attr") {
		    p4tidy_proc($cell, $part_attr, $part_attr, $part_pat, 1);
		}
		
		#symbol
		$sm_attr = "$cell/$cell" . $sm_attr_sfx;
		$sm_pat  = $cell . $sm_cell_sfx;
		if (-f "$sm_attr") {
		    p4tidy_proc($cell, $sm_attr, $sm_attr, $sm_pat, 1);
		}

		#schematic
		$sch_attr = "$cell/schematic/$sch_name" . $sch_attr_sfx;
		$sch_pat  = $sch_name . $sch_cell_sfx;
		if (-f "$sch_attr") {
		    p4tidy_proc("$cell/schematic", $sch_attr, $sch_attr, $sch_pat, 2);
		}
		
	    }

	}
    }

    exit 0;
}

sub p4tidy_proc {
    my ($orig_cell, $attr_file, $orig_attr_file, $ic_pat, $mag_value) = @_;

    my ($cmd);
    my ($openStat, $expectedStat, $orig_cnt, $del_cmd);
    my ($icfile, @allicfiles, @deletelist, $i);
    my (@keep_list, $num_to_keep);


    # ok, attr file exists
    opendir CELLDIR, $orig_cell;

    $openStat = &Icp4::openStat($attr_file);
    $expectedStat = &Icp4::p4_stat_constant("NOT_OPENED");
    if ($opt{D}) {
	print "# DEBUG: \"$attr_file\" open stat=$openStat  expected stat=$expectedStat\n";
    }
	    
    if ($openStat == &Icp4::p4_stat_constant("UNKNOWN")) {
	print "WARNING: File $attr_file not checked into p4 (code $openStat).  Skipping.\n";
	return;
    }
    if ($openStat != $expectedStat) {
	print "WARNING: File $attr_file writable (code $openStat).  Skipping.\n";
	return;
    }
    
    #@keep_list = &Icp4::get_keep_list($orig_attr_file);
    &Icp4::get_keep_list($orig_attr_file, \@keep_list);

    if ($opt{D}) {
	&Icp4::list_debug_print("keep_list", @keep_list);
    }

    if ($opt{k}) {
	$orig_cnt = $#keep_list;
	$num_to_keep = $opt{k} * $mag_value;
	for ($i=0; $i <= ($orig_cnt - $num_to_keep ); $i++) {
	    shift @keep_list;
	}

	if ($opt{D}) {
	    print "# DEBUG: After trimming ... $#keep_list\n";
	    &Icp4::list_debug_print("keep_list", @keep_list);
	}
    }

    @allicfiles = grep /$ic_pat/, readdir CELLDIR;
    
    if ($opt{D}) {
	&Icp4::list_debug_print("allicfiles", @allicfiles);
    }

    closedir CELLDIR;
    
    @deletelist = @allicfiles;
    foreach $icfile (@keep_list) {
	# bad:
	# @deletelist = grep !/^$icfile$/, @deletelist;
	# good:
	@deletelist = grep { $_ ne "$icfile" } @deletelist;
    }
    if ($opt{D}) {
	&Icp4::list_debug_print("deletelist", @deletelist);
    }

    if ($opt{r}) {
	$del_cmd = "/bin/rm -f";
    } elsif ($opt{O}) {
	$del_cmd = "p4 -y obliterate";
    } elsif ($opt{c}) {
	$del_cmd = $opt{c};
    } else {
	$del_cmd = "p4 delete";
    }

    foreach $i (@deletelist) {
	$i =~ s/\$/\\\$/g;
	$cmd = "$del_cmd $orig_cell/$i";
	if ($opt{n}) {
	    print "INFO: (not run) $cmd\n";
	} else {
	    print "INFO: Running $cmd\n";
	    system $cmd;
	}
    }

}