#!/usr/bin/perl6
# your code goes here

use NativeCall;

class DIR is repr('CPointer') {

    sub opendir(Str) of Pointer is native(Str) { * }

    method new(Str $dir)  {
        return nativecast(DIR, opendir($dir));
    }

    class Dirent is repr('CStruct') {
        has int64 $.ino;
        has int64 $.off;
        has uint16 $.reclen;
        has uint8 $.type;
        has CArray[int8] $.name;

        submethod TWEAK() {
            $!ino  = long.new(0);
            $!off  = long.new(0);
            $!reclen = uint16.new(0);
            $!type   = uint8.new(0);
            $!name := CArray[int8].new;
            $!name[$_] = 0 for ^256;
        }

        method name() {
            say $!name[0];
            #my Buf $buf .= new;
            #$buf[$_] = $!name[$_] for ^256;
            #$buf.decode('utf8');
        }
    }

    sub readdir(DIR) of Pointer is native(Str) { * }

    sub readdir_r(DIR, Dirent is rw, Pointer[Dirent] is rw) of int32 is native(Str) { * }

    method read() of Dirent {
        my $ptr = nativecast(Pointer[Dirent], readdir(self));
        return $ptr.deref;
    }

    method read_r() of Dirent {
        my $dirent = Dirent.new;
        my $res = Pointer[Dirent].new;
        say "ret = ", readdir_r(self, $dirent, $res);
        say $res;
        $dirent;
    }

    sub closedir(DIR) of int32 is native(Str) { * }

    method close() of int {
        closedir(self);
    }

    method error() {
        my $error := cglobal('libc.so.6', 'errno', int32);
        $error;
    }

    submethod DESTORY() {

    }
}

my $current = DIR.new(".");

dd $current;

for ^3 {
    my $dirent = $current.read_r;
    dd $dirent;
    say $dirent.name;
}

$current.close;