### ----------------------------------------------------
### -- PDF::Class
### -- Licenses: Artistic-2.0
### -- Authors: David Warring
### -- File: lib/PDF/Class/OutlineNode.rakumod
### ----------------------------------------------------
unit role PDF::Class::OutlineNode;

use PDF::COS;
use PDF::Destination :coerce-dest, :DestinationLike, :DestRef;
sub siblings($first) is rw {
    my class Siblings does Iterable {
        has $.first is required;
        my class Iteration does Iterator {
            has $.cur is required;
            method pull-one {
                my $this = $!cur;
                $_ = .Next with $!cur;
                $this // IterationEnd;
            }
        }
        method iterator { Iteration.new: cur => $!first }
    }.new(:$first);
}
method add-kid(Hash $kid is copy = {}) {
    my $grand-kids = $kid<kids>:delete;
    my DestRef $dest;
    with $kid<dest>:delete {
        when DestRef { $dest = $_; }
        when DestinationLike|Str  { $dest = coerce-dest($_, DestRef); }
        default { warn "ignoring outline dest: {.gist}" }
    }
    $kid = (require PDF::Outline).COERCE: $kid;
    $kid.Dest = $_ with $dest;
    $kid.Parent = self;
    with self.Last {
        .Next = $kid;
        $kid.Prev = $_;
    }
    self.Last = $kid;
    self.First //= $kid;
    my %seen{Any};
    my $node = $kid;

    while $node {
        last if %seen{$node}++;
        last unless $node.can('Parent');
        $node .= Parent;
        $node.Count++;
    }
    $kid.kids = $_ with $grand-kids;
    $kid;
}
#| .get Proxy Fetch not working
method get-kids { siblings(self.First) }
method kids is rw {
    Proxy.new(
        FETCH => { siblings(self.First) },
        STORE => -> $, @kids {
            self<First Last>:delete;
            self.add-kid($_) for @kids;
        });
}
method count { .abs with $.Count }
method is-open is rw {
    Proxy.new(
        FETCH => -> $ { $_ >= 0 with $.Count },
        STORE => -> $, Bool() $open {
            $_ = .abs * ($open ?? 1 !! -1)
                with $.Count
        }
    )
}


