### ----------------------------------------------------
### -- IRC::Channel::Log
### -- Licenses: Artistic-2.0
### -- Authors: Elizabeth Mattijsen
### -- File: t/01-basic.rakutest
### ----------------------------------------------------
use Test;
use IRC::Log::Colabti:auth<zef:lizmat>;
use IRC::Channel::Log:auth<zef:lizmat>;;

plan 98;

my $logdir := $?FILE.IO.sibling('raku');
my $state  := $?FILE.IO.sibling('state');
my $class  := IRC::Log::Colabti;

sub generator($nick) { "$nick.color" }

#-------------------------------------------------------------------------------
# Generic tests

my $channel = IRC::Channel::Log.new(:$logdir, :$class, :&generator, :$state);
is $channel.problems.elems, 0, 'there should be no problems';
isa-ok $channel, IRC::Channel::Log;

#.say for $channel.entries(:around-target<2021-04-23Z09:33>, :conversation);
#=finish

my str @dates = $channel.dates;
is +@dates, 2, 'did we get 2 dates';
is @dates.head, '2021-04-23', 'is the first date ok';
is @dates.tail, '2021-04-24', 'is the last date ok';

nok $channel.initial-topic('2021-04-23'), 'no topic initially';
is $channel.initial-topic('2021-04-24').text, 'Raku Rocks!', 'topic ok';

my %problems := $channel.problems;
is +%problems, 0, 'did we get correct number of problems';

my @nicks = $channel.nick-names;
is +@nicks, 260, 'did we get correct number of nicks';
is @nicks.sort.skip.head, "APic", 'is the first real nick ok';
is @nicks.sort.tail, "|Sno|", 'is the last nick ok';

#-------------------------------------------------------------------------------
# Tests on number of elements selected

for False, True -> $reverse {
    is $channel.entries(:$reverse).elems, 1230,
      'did we get correct total entries';
    is $channel.entries(:control, :$reverse).elems, 767,
      'did we get correct number of control messages';
    is $channel.entries(:conversation, :$reverse).elems, 464,
      'did we get correct number of  messages';

    is $channel.entries(:nick-names<lizmat>, :$reverse).elems, 119,
      'did we get correct number of entries by lizmat';

    is $channel.entries(
      :control, :nick-names<lizmat>, :$reverse
    ).elems, 2,
      'did we get correct number of control messages by lizmat';
    is $channel.entries(
      :conversation, :nick-names<lizmat>, :$reverse
    ).elems, 118,
      'did we get correct number of conversation messages by lizmat';

    is $channel.entries(
      :dates<2021-04-23>, :nick-names<lizmat>, :$reverse
    ).elems, 70,
      'did we get correct number of entries by lizmat on 2021-04-23';
    is $channel.entries(
      :dates<2021-04-24>, :nick-names<lizmat>, :$reverse
    ).elems, 49,
      'did we get correct number of entries by lizmat on 2021-04-24';
    is $channel.entries(
      :dates("2021-04-20".Date .. "2021-04-23".Date),
      :nick-names<lizmat>, :$reverse
    ).elems, 70, 'correct number of entries by lizmat from Date range';
    is $channel.entries(
      :nick-names<lizmat japhb>, :$reverse
    ).elems, 147,
      'correct number of entries by lizmat or japhb';

    is $channel.entries(:starts-with<m:>, :$reverse).elems, 17,
      'correct number of entries that start with m:';
    is $channel.entries(:starts-with<m: how>, :ignorecase, :$reverse).elems, 22,
      'correct number of entries that start with m: or how ignorecased';

    is $channel.entries(:contains<answer>, :$reverse).elems, 4,
      'correct number of entries with text "answer"';
    is $channel.entries(:contains<this answer>, :$reverse).elems, 30,
      'correct number of entries with text "this" or "answer"';
    is $channel.entries(:contains<this answer>, :all, :$reverse).elems, 1,
      'correct number of entries with text "this" and "answer"';

    is $channel.entries(:words<with>, :$reverse).elems, 30,
      'correct number of entries with the word "with"';
    is $channel.entries(:words<they always>, :$reverse).elems, 14,
      'correct number of entries with the word "they" or "always"';
    is $channel.entries(:words<they always>, :all, :$reverse).elems, 1,
      'correct number of entries with the word "they" and "always"';

#    is $channel.entries(
#      :around-target<2021-04-23Z09:33>, :$reverse
#    ).elems, 21,
#      'did we get all 21 entries around the target?';
#    is $channel.entries(
#      :around-target<2021-04-23Z09:33>, :nr-entries(5), :$reverse
#    ).elems, 11,
#
    is $channel.entries(
      :targets<2021-04-23Z09:33 2021-04-23Z14:04-0007 2021-04-24Z08:48-0001>,
      :$reverse
    ).elems, 3,
      'did we get all 3 targets?';

    is $channel.entries(
      :matches(/ [^ | \s+] \d\d+ [\s+ | $] /), :$reverse
    ).elems, 9,
      'correct number of whitespaced multi-digit numbers';
}

is $channel.entries(:lt-target<2021-04-24Z02:50>, :words<the>).elems, 60,
  'did we get all entries before the target?';
is $channel.entries(:le-target<2021-04-24Z02:50>, :words<the>).elems, 61,
  'did we get all entries until the target?';
is $channel.entries(:ge-target<2021-04-23Z23:38>, :words<the>).elems, 79,
  'did we get all entries from the target?';
is $channel.entries(:gt-target<2021-04-23Z23:38>, :words<the>).elems, 78,
  'did we get all entries after the target?';

#-------------------------------------------------------------------------------
# Same tests, but now checking on first / last entry

sub first-last($first, $last = $first, |c) is test-assertion {
    subtest "checking first/last on {c.raku}" => {
        plan 4;

        is $channel.entries(|c).head.gist, $first,
          'is first entry correct';
        is $channel.entries(:reverse, |c).tail.gist, $first,
          'is last entry on reverse correct';

        is $channel.entries(|c).tail.gist, $last,
          'is last entry correct';
        is $channel.entries(:reverse, |c).head.gist, $last,
          'is first entry on reverse correct';
    }
}

my $first-control := '[00:04] *** Geth left';
my $last-control  := "[23:46] *** aborazmeh left";
my $first-text := '[06:31] <El_Che> Xliff: is your network faster than your disk?';
my $last-text  := "[23:44] <raydiak> heh, even that isn't right. leg is also lexographic; cmp (not string-specific) is by codepoint, and coll is something I don't fully understand yet";

first-last $first-control, $last-control;
first-last $first-control, $last-control, :control;
first-last $first-text,    $last-text,    :!control;
first-last $first-text,    $last-text,    :conversation;
first-last $first-control, $last-control, :!conversation;

first-last
  '[08:39] <lizmat> :q',
  '[22:31] * lizmat is glad that japhb is around to answer questions while she hits the sack',
  :nick-names<lizmat>;
first-last
  '[11:09] *** lizmat is now known as lismat',
  '[23:48] *** lizmat changes topic to: Raku Rocks!',
  :nick-names<lizmat>, :control;
first-last
  '[08:39] <lizmat> :q',
  '[22:31] * lizmat is glad that japhb is around to answer questions while she hits the sack',
  :nick-names<lizmat>, :conversation;

first-last
  '[11:53] <lizmat> that would be *very* futuristic',
  '[22:31] * lizmat is glad that japhb is around to answer questions while she hits the sack',
  :nick-names<lizmat>, :dates<2021-04-24>;

first-last
  '[08:39] <lizmat> :q',
  '[23:48] *** lizmat changes topic to: Raku Rocks!',
  :nick-names<lizmat>, :dates("2021-04-20".Date .. "2021-04-23".Date);

first-last
  '[08:39] <lizmat> :q',
  '[23:44] <japhb> ^^ Why does that even work?  Why does &?BLOCK go to the given and not to the when?',
  :nick-names<lizmat japhb>;

first-last
  '[09:30] <brtastic> m: sub (@arr) { @arr.push(5).say }((1, 2, 3))',
  '[23:44] <japhb> m: given 5 { when * % 2 { say "Odd"; &?BLOCK(6) }; when * %% 2 { say "Even" }}',
  :starts-with<m:>;

first-last
  '[09:25] <PimDaniel> How may i sort a hash by a part of his key?',
  '[23:44] <japhb> m: given 5 { when * % 2 { say "Odd"; &?BLOCK(6) }; when * %% 2 { say "Even" }}',
  :starts-with< m: how >, :ignorecase;

first-last
  "[13:13] <Juerd> IMHO the whole public namespace hierarchy doesn't work anyway. Different people would answer this question differently and there's no official guidance.",
  '[22:31] * lizmat is glad that japhb is around to answer questions while she hits the sack',
  :contains<answer>;

first-last
  '[09:30] <brtastic> how do I make this argument into Array?',
  "[22:56] <raydiak> wonder if there'd be much difference using a different dataset, especially one more deeply nested, or more numbers instead of strings, etc. if you were wanting to use this for MUGS, I'd expect many games to use a lot more numbers",
  :contains<this answer>;

first-last
  "[13:13] <Juerd> IMHO the whole public namespace hierarchy doesn't work anyway. Different people would answer this question differently and there's no official guidance.",
  :contains<this answer>, :all;

first-last
  '[09:30] <PimDaniel> From the lower to the bigger. They just can be many with the same number.',
  "[23:16] <japhb> Nope, haven't done that yet.  I wish we had a good per-line profiler, like NYTProf is for perl5, because the routines here are HUGE with big branching structures, so per-call statistics are too rough.  :-/",
  :words<with>;

first-last
  '[09:28] <lizmat> do they need to sort as number or as string ?  I assume as number ?',
  '[22:32] <japhb> raydiak: When you upload packages to zef or cpan, you are uploading a snapshot tarball of a particular version.  So they can keep all the versions they want.',
  :words<always they>;

first-last
  '[09:29] <lizmat> and are they always Int?',
  :words<always they>, :all;

first-last
  "[23:38] <summerisle> demostanis[m]: if it's any help (it probably isn't) it takes 2 minutes and 12 seconds to compile the rakudo distribution from Gentoo, this is with 56 threads on a 64 thread host.",
  "[23:44] <japhb> ^^ Why does that even work?  Why does &?BLOCK go to the given and not to the when?",
  :ge-target<2021-04-23Z23:38>, :words<the>;

first-last
  "[09:27] <PimDaniel> My has has : these kind of keys : '33:A/B' , '9:Y/Q' '117:C/G' and i need to sort by the first number befor the ':'.",
  "[23:38] <summerisle> demostanis[m]: if it's any help (it probably isn't) it takes 2 minutes and 12 seconds to compile the rakudo distribution from Gentoo, this is with 56 threads on a 64 thread host.",
  :le-target<2021-04-23Z23:38>, :words<the>;

first-last
  "[02:27] <raydiak> demostanis[m]: I know it's several hours after the fact, but maybe you'll see this in the scrollback. 12m34s on a ryzen 5 2500u laptop (4 smt2 cores @ 2ghz/3.6ghz turbo) running manjaro...but I forgot to pass -j so that's single-threaded :P",
  "[23:44] <japhb> ^^ Why does that even work?  Why does &?BLOCK go to the given and not to the when?",
  :gt-target<2021-04-23Z23:38>, :words<the>;

first-last
  "[09:27] <PimDaniel> My has has : these kind of keys : '33:A/B' , '9:Y/Q' '117:C/G' and i need to sort by the first number befor the ':'.",
  "[02:46] <moon-child> (well, nqp and rakudo probably _could_ be built in parallel, but the makefile isn't set up in such a way that make knows how to do that)",
  :lt-target<2021-04-24Z02:50>, :words<the>;

first-last
  '[09:31] <lizmat> m: sub (@arr) { @arr.push(5).say }([1, 2, 3])',
  '[09:35] <PimDaniel> I\'d expect this kind of form : for %hash.sort(<condition>) -> $k { ...} ',
  :around-target<2021-04-23Z09:33>, :conversation;

first-last
  "[09:33] <PimDaniel> This is to display hash and i must display the whole key.",
  "[08:48] <El_Che> so like dist do, I would package modules separately",
  :targets<2021-04-23Z09:33 2021-04-23Z14:04-0007 2021-04-24Z08:48-0001>;

first-last
  "[09:31] <brtastic> ah cool",
  "[09:34] <camelia> rakudo-moar ea102883d: OUTPUT: «[1 2 3 5]␤»",
  :around-target<2021-04-23Z09:33>, :conversation, :5nr-entries;

first-last
  '[13:52] <lizmat> 404 for the win!',
  '[21:16] <lizmat> m: my Blob[Any] $foo = "foo", 21',
  :matches(/ [^ | \s+] \d\d+ [\s+ | $] /);

#-------------------------------------------------------------------------------
# Utility methods tests

is-deeply
  $channel.aliases-for-nick-name("simcop2387"),
  (my str @ = <simcop2387 simcop2387_>),
  'Did we get all the aliases for the nick name';
is $channel.cleaned-nick-name("simcop2387"), "simcop",
  'did we get a cleaned nick name';

is $channel.this-date('2021-04-23'), '2021-04-23', 'did we get this date';
is $channel.this-date('2021-04-22'), '2021-04-23', 'did we get next date';
is $channel.this-date('2021-04-25'), '2021-04-24', 'did we get previous date';

is $channel.next-date('2021-04-23'), '2021-04-24', 'did we get next date';
is-deeply $channel.next-date('2021-04-24'), Nil, 'is last date handled ok';

is $channel.prev-date('2021-04-24'), '2021-04-23', 'did we get previous date';
is-deeply $channel.prev-date('2021-04-23'), Nil, 'is first date handled ok';

isa-ok $channel.log('2021-04-23'), IRC::Log::Colabti;
is-deeply $channel.log('2021-04-25'), Nil, 'no log on 2021-04-25';

ok $channel.is-first-date-of-month('2021-04-23'),  'first date in month ok';
ok $channel.is-first-date-of-year('2021-04-23'),   'first date in year ok';
nok $channel.is-first-date-of-month('2021-04-24'), 'first date in month nok';
nok $channel.is-first-date-of-year('2021-04-24'),  'first date in year nok';

#-------------------------------------------------------------------------------
# Test shutdown behaviour

$state.mkdir;
my $colors := $state.add('colors.json');
$channel.shutdown;
ok $colors.e, 'did we save state information';
$colors.unlink;  # clean up
$state.rmdir;

# vim: expandtab shiftwidth=4


