use v6.d;
use RakuDoc::Templates;
use RakuDoc::Render;

unit class RakuDoc::Plugin::HTML::ListFiles;
has %.config =
    :name-space<listfiles>,
	:version<0.2.0>,
    :block-name('ListFiles'),
	:license<Artistic-2.0>,
	:credit<finanalyst, wayland>,
	:authors<finanalyst, wayland>,
    :scss([self.add-scss,1],),
;
method enable( RakuDoc::Processor:D $rdp ) {
    $rdp.add-templates( $.templates, :source<ListFiles plugin> );
    $rdp.add-data( %!config<name-space>, %!config );
}
method !file-title(%data, $fn) {
    (%data<title> eq '' or %data<title> eq 'NO_TITLE') ?? $fn !! %data<title>
}
method !sort-key(%data, $fn, $sort-by --> Str) {
    my $title = self!file-title(%data, $fn);
    my $title-key = $title.lc;
    $sort-by.chars or return "1|$title-key|$title-key";

    my $raw = do given $sort-by {
        when 'title' { $title }
        when 'subtitle' | 'route' { %data{$sort-by} // '' }
        default { %data<config>{$sort-by} // '' }
    }
    ;
    my $sort-value = $raw.Str.trim;
    $sort-value eq '' and return "1|$title-key|$title-key";

    $sort-value ~~ /^ '-'? \d+ $/
        ?? "0|{sprintf('%020d', $sort-value.Int)}|$title-key"
        !! "1|{$sort-value.lc}|$title-key"
}
method templates {
    my regex s-pair {
        (<-[=]>+) \= (.+?)
    };
    my regex select {
        ^ <s-pair>+ % [\,\s] $
    };
    %(
        ListFiles => sub (%prm, $tmpl) {
            return qq:to/ERROR/ unless %prm<select>:exists;
                <div class="listf-error">
                ListFiles needs :select key with criteria.
                </div>
                ERROR

            my $sel = %prm<select>.Str;
            my %criteria;
            if $sel ~~ / <select> / {
                for $/<select><s-pair> { %criteria{~$_[0].trim} = ~$_[1] }
            }
            else {
                return qq:to/ERROR/
                    <div class="listf-error">
                    ListFiles :select key does not parse, must be one pair of form ｢\\S+ \\s* = \\s* \\S+｣
                    or a comma-separated list of such pairs. Got
                    { %prm<select> }
                    </div>
                    ERROR

                 }
            # check meta data exists
            return q:to/ERROR/ unless $tmpl.globals.data<listfiles><meta>:exists;
                <div class="listf-error">ListFiles has no collected data
                </div>
                ERROR

            my @sel-files;
            for $tmpl.globals.data<listfiles><meta>.kv -> $fn, %data {
                # data is config, title, desc
                my Bool $ok;
                for %criteria.kv -> $k, $v {
                    if $v eq '!' {
                        $ok = %data<config>{$k}:!exists;
                    }
                    else {
                        $ok = (%data<config>{$k}:exists and ?(%data<config>{$k} ~~ / <$v> /));
                    }
                    last unless $ok
                }
                next unless $ok;
                my $title = self!file-title(%data, $fn);
                @sel-files.push: [
                    self!sort-key(%data, $fn, %prm<sort-by>:exists ?? %prm<sort-by>.Str !! ''),
                    $title,
                    (%data<subtitle> ?? %data<subtitle> !! 'No description found'),
                    %data<route> // $fn
                ];
            }
            my $rv = qq:to/FIRST/;
                    <div class="listf-container" id="{ $tmpl.globals.escape.( %prm<target>) }">
                    FIRST
            my $cap = qq:to/CAP/;
                    <p class="listf-caption">{ %prm<raw>:exists ?? %prm<raw>.Str.trim !! 'No caption'  }</p>
                    CAP
            for  @sel-files.sort(*.[0]) -> ($sort, $nm, $desc, $route) {
                $rv ~= qq:to/NOFL/;
                    <div class="listf-file">
                    $cap
                    <a class="listf-link" href="$route">$nm\</a>
                    <p class="desc">$desc\</p>\</div>
                    NOFL
                $cap = '';
            }
            unless +@sel-files {
                $rv ~= qq:to/NOFL/;
                    <div class="listf-file">
                    $cap
                    <p class="desc">No files meet the criteria: {%criteria.raku}\</p>
                    </div>
                    NOFL
            }
            $rv ~= '</div>'
        },
    )
}
method add-scss {
    q:to/SCSS/;
    .listf-container {
      display: flex;
      flex-direction: column;
      margin-bottom: 1.25rem;
      font-size: 1rem;
      font-weight: 500;
      line-height: 1.5;
      border: 1px solid #cccccc;
      border-bottom: 5px solid #d9d9d9;
      box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.07);
      .listf-caption {
          display: flex;
          justify-content: center;
          background: #f2f2f2;
          border-bottom: 1px solid #cccccc;
          color: #83858D;
      }
      .listf-file {
          display: inline-block;
          border-top: 1px solid #cccccc;
          border-bottom: 1px solid #cccccc;
          break-inside: avoid;
          .listf-link {
              display: inline-block;
              width: 100%;
              text-align: center;
              padding-top: 0.25rem;
          }
          p.desc {
              padding-left: 0.5rem;
              padding-right: 0.5rem;
              margin-bottom: 0.25rem;
          }
      }
    }
    .listf-error {
      color: red;
      font-size: xlarge;
    }
    SCSS
}
