#!/usr/bin/env raku
use v6.e.PREVIEW;
use Vikna::Tracer;
use Template::Mustache;
# use Data::Dump;

my %*SUB-MAIN-OPTS =
    :named-anywhere,
    ;

multi MAIN('list-sessions', Str :$db-file = 'Vikna.sqlite') {
    my $tr = Vikna::Tracer.new: db-name => $db-file;
    for $tr.sessions {
        say .id.fmt('%4d '), ~.started.local, " [{.records.elems.fmt('%6d')}] ", .name;
    }
}

multi MAIN( Str:D $format where * ~~ (any Vikna::Tracer.templates.keys),
            Int :$session?,
            Str:D :$db-file = 'Vikna.sqlite',
            Str :o(:$output)
        )
{
    my $tr = Vikna::Tracer.new: db-name => $db-file;
    my $fh = $*OUT;
    LEAVE $fh.close if $output;
    with $output {
        $fh = .IO.open: :w;
    }

    my $tmpl = Vikna::Tracer.templates{$format};

    my @sessions;
    with $session {
        @sessions = $tr.session($_)
    }
    else {
        @sessions = $tr.sessions;
    }

    say "Loaded ", +@sessions, " sessions";

    my %data = session => [];
    for @sessions -> $sess {
        say "Processing session ", $sess.id, ", records: ", $sess.records.elems;
        my %sess = id => .id, started => .started, name => .name with $sess;
        my @flows = $sess.records.flows; # $sess.records.map( *.flow-id ).unique.sort;
        my @flow-names = '' xx +@flows;
        my %fl-idx = @flows.antipairs;
        %sess<flows> = @flows.map( { { flow => ~$_ } } ).list;
        %sess<tbl_columns> = @flows.elems + 2;
        my $reccount = 0;
        %sess<rows> = (gather {
            for $sess.records {
                ++$reccount;
                $*ERR.print: $reccount.fmt("REC: %6d\r") if $reccount % 100 == 0;
                my %rec;
                my $fl-idx = %fl-idx{ .flow-id };

                if @flow-names[$fl-idx] ne .flow-name {
                    my %flow-row;
                    my @flow-cols = [ { cell => { } } xx +@flow-names ];
                    @flow-cols[$fl-idx]<cell> = %( flow_name => (.flow-name || '*anon*') );
                    @flow-names[$fl-idx] = .flow-name;
                    %flow-row<id> = .id;
                    %flow-row<time> = .time;
                    %flow-row<cols> = @flow-cols;
                    # say Dump(%flow-row, :skip-methods);
                    take { flow_name => %flow-row };
                }

                %rec<cols> = [ { cell => { } } xx +@flows ];
                %rec<time> = .time;
                %rec<id> = .id;
                %rec<flow_name> = .flow-name;
                %rec<cols>[ $fl-idx ]<cell> = %(
                    object_id   => .object-id,
                    message     => [ .message.split("\n").map( { %( line => $_ ) } ) ],
                    rec_class   => 'tracer_' ~ .class,
                );
                take { record => %rec };
            }
        }).hyper(:degree(32));
        %data<session>.push: %sess;
    }

    # say Dump(%data, :skip-methods);
    say "Rendering the page...";
    my $mustache = Template::Mustache.new;
    $fh.print: $mustache.render( slurp(~$tmpl), %data );
}

multi MAIN( Str $format, |c) {
    die "Unsupported format {$format}. Choose any of: ", Vikna::Tracer.templates.keys.join(", ");
}
