#!/usr/bin/perl -w

use strict;
use Data::Dumper;

#my $netlist = "gnetlist";
my $netlist = "lepton-netlist";

my %pfx = (
    "" => 1,
    p => -12,
    n => -9,
    u => -6,
    m => -3,
    k => 3,
    M => 6,
);
my %pfxmap = (
    # just something that makes p < n etc.
    p => "d",
    n => "e",
    u => "f",
    m => "g",
    "" => "h", # no prefix, as in 1; 1m < 1 < 1k
    k => "i",
    M => "j",
);
my %part;
my @hdr;

sub sortstr($) {
    my $r = shift;
    my @arr = @$r;

    my $ta = $arr[2];
    my $va = "Z" . $ta;
    if ($ta =~ m/^([0-9.]+)([pnumkM]?)( .*)?/) {
	my $v = $1;
	my $k = $pfxmap{$2};
	my $ext = $3 // "";
	if (!defined($k)) { $k = "h"; }
	$va = sprintf(" %s%7.3f%s", $k, $v, $ext);
    }

    $ta = $arr[3];
    if ($ta =~ m/(.*[a-zA-Z])(\d+)/) {
	$ta = sprintf("%s%02d", $1, $2);
    } elsif ($ta =~ m/([a-zA-Z])/) {
	$ta = sprintf("%s  ", $1);
    } else {
	print STDERR "sortstr <$ta>\n";
    }

    my $str = "$arr[0] $arr[1] $va $ta";
    #print "$str\n";
    #exit(0);
    return $str;
}
sub sort_pfx {
    return sortstr($a) cmp sortstr($b);
}

sub sortrd_key( $ ) {
    my $rd = shift;

    if ( $rd =~ m/^([a-zA-Z]*)(\d+)(.*)$/ ) {
	my $a = $1;
	my $b = $2;
	my $c = $3;
	if (!defined($a)) { $a = ""; }
	if (defined($c)) {
	    $c = &sortrd_key( $c );
	} else {
	    $c = "";
	}
	return sprintf "%s%03d%s", $a, $b, $c;
    } else {
	return $rd;
    }
}
sub sort_rd {
    sortrd_key($a) cmp sortrd_key($b);
}

sub other_bom(@) {
    my @line = @_;

    print "Qty,Value,Device,Package,Parts,Description,LINK\n";

    for my $line (@line) {
	my ($device, $footprint, $value, @refdes) = @$line;
	my $cnt = @refdes;

	print "$cnt, $value, $device, $footprint, ", join(" ", @refdes), ", , \n";
    }

}

sub run($) {
    my $file = shift;
    #`echo "device\nfootprint\nvalue" > attribs`;

    #print `$netlist -g bom2 -o $file.list $file`;
    if (!open(FH, "$file.list")) {
	warn("no file $file.list");
	return;
    }
    # I get the following format:
    #   refdes:device:footprint:value:qty
    my $col = 5;
    my @line;
    my @len = (0)x3;
    while (<FH>) {
	chomp;
	if (m/^refdes/) {
	    @hdr = split(/:/,$_,$col);
	    # I want following order: device footprint value refdes
	    @hdr = @hdr[1,2,3,0];
	    next;
	}
	next if (m/^\./);
	next if (m/^U\?(:unknown)+:\d+$/);
	my @fld = split(/:/, $_, $col);
	if (@fld != $col) {
	    warn("not $col cols <$_>");
	    next;
	}
	pop @fld; # skip quantity which is always eq. number of refdes's
	my @refdes = split(/,/,$fld[0]);
	@refdes = sort sort_rd @refdes;
	# I want following order: device footprint value refdes
	@fld = @fld[1,2,3];
	for (my $ix = 0; $ix < @fld; $ix++) {
	    my $l = length($fld[$ix]);
	    if ($len[$ix] < $l) {
		$len[$ix] = $l;
	    }
	}
	push @line, [ @fld, @refdes ];
    }
    close(FH);
    @line = sort sort_pfx @line;

    my $fmt1 = sprintf("%%-%ds %%-%ds %%-%ds", @len[0..2]);
    my $fmt = $fmt1 . " %s\n";
    if (!open(F1, ">$file.list1.txt")) {
	warn("cannot open output file ($file.list1.txt)");
	return;
    }
    if (!open(F2, ">$file.list2.txt")) {
	warn("cannot open output file ($file.list2.txt)");
	return;
    }
    printf(F1 $fmt, @hdr);
    printf(F2 $fmt, @hdr);
    printf(F2 "\n");
    for my $l (@line) {
	my ($device, $footprint, $value, @refdes) = @$l;
	my $cnt = @refdes;
	my $key = sprintf($fmt1, $device, $footprint, $value);

	printf(F1 "\n");
	for my $rd (@refdes) {
	    print F1 "$key $rd\n"; # Note: F1 here
	}

	printf(F2 "%s %2d %s\n", $key, $cnt, join(" ", @refdes));
    }
    close(F1);
    close(F2);
    `cat $file.list1.txt | a2ps -o- -s1 -1 -q -f11 -B   --borders=no > $file.list1.ps`;
    `cat $file.list2.txt | a2ps -o- -s1 -1 -q -f8 -B -r --borders=no > $file.list2.ps`;

    other_bom(@line);
}

sub main() {
    for my $f (@ARGV) {
	run($f);
    }
}

main();
