#!/usr/bin/env perl6

use nqp;
use Getopt::Advance;

my OptionSet $os .= new;

$os.push(
    'c=a',
    'c source file extension list.',
    value => [ "c", ]
);
$os.push(
    'h=a',
    'head file extension list.',
    value => [ "h", ]
);
$os.push(
    'cpp|=a',
    'cpp source file extension list.',
    value => Q :w ! C cpp c++ cxx hpp cc h++ hh hxx!
);
$os.push(
    'cfg|=a',
    'config file extension list.',
    value => Q :w ! ini config conf cfg xml !
);
$os.push(
    'm=a',
    'makefile extension list.',
    value => ["mk", ]
);
$os.push(
    'w=a',
    'match whole filename.',
    value => Q :w ! makefile Makefile !
);
$os.push(
    'a=a',
    'addition extension list.',
);
$os.push(
    'i=b',
    'enable ignore case mode.'
);
$os.push(
    'no|=a',
    'exclude file category.',
);
$os.push(
    'only|=s',
    'only search given category.',
);
$os.push(
    'd|debug=b',
    'print debug message.'
);
$os.push(
    'd2|=b',
    'show file in debug mode.'
);
my $id = $os.insert-pos(
    "directory",
    sub find-and-print-source($os, $dira) {
        my @stack = $dira.value;
        my @ext = [];
        with $os<only> {
            fail "Not recognized category: {$_}." unless $_ (elem) < c h cpp cfg m a w >;
            @ext = $os{$_} // [];
        } else {
            for < c h cpp cfg m a > -> $opt {
                if $opt !(elem) @($os<no>) {
                    @ext.append($os{$opt} // []);
                }
            }
        }

        note "GET ALL EXT => ", @ext if $os<d>;

        my $supplier = Supplier.new;

        react {
            start whenever $supplier.Supply {
                put Q :qq '"$_"';
                LAST done
            }
        }

        while @stack {
            note "CURR FILES => ", @stack if $os<d2>;
            my @stack-t = (@stack.race.map(
                                  -> $_ {
                                      note "\t|GOT FILE => ", $_ if $os<d>;
                                      when nqp::lstat(nqp::unbox_s($_), nqp::const::STAT_ISDIR) == 1 {
                                          .&getSubFiles;
                                      }
                                      # regex search is slow than ext match
                                      when ($_.substr(($_.index(".") // -1) + 1) (elem) @ext) || ($_ (elem) @($os<w>)) { # / \. @ext $/ {
                                          $supplier.emit($_);
                                          ();
                                      }
                                      default {
                                          ();
                                      }
                                  }
                              ).flat);
            @stack = @stack-t;
        };
    },
    :last
);

&getopt($os);

sub getSubFiles($path) {
    my @ret := [];
    my $dh := nqp::opendir($path);

    while (my $f = nqp::nextfiledir($dh)) {
        @ret.push("$path/$f") if $f ne "." | "..";
    }

    nqp::closedir($dh);

    return @ret;
}
