### ----------------------------------------------------
### -- CRDT
### -- Licenses: Artistic-2.0
### -- Authors: Fernando Correa
### -- File: lib/G-Set.rakumod
### ----------------------------------------------------
use CRDT;
unit class G-Set does CRDT does Associative;

class X::G-Set::Unset is Exception {
    method message { "A item cannot be unset on a G-Set" }
}

has             %!values is SetHash handles <keys elems>;
has Lock::Async $!lock .= new;

method !values is rw { %!values }

method export {
    await $!lock.lock;
    LEAVE $!lock.unlock;
    %!values
}

method set($item) {
    await $!lock.lock;
    LEAVE {
        $!lock.unlock;
        self!emit-change;
    }
    %!values.set: $item;
    $item
}

method unset($) { X::G-Set::Unset.new.throw }

method AT-KEY($item) {
    await $!lock.lock;
    LEAVE $!lock.unlock;
    %!values.AT-KEY: $item
}

method copy {
    my $obj = ::?CLASS.new;
    $obj!values = |%!values;
    $obj
}


multi method merge(::?CLASS $b) {
    self.merge: $b.export;
}

multi method merge($data) {
    await $!lock.lock;
    LEAVE {
        $!lock.unlock;
        self!emit-merge;
    }
    %!values = |(%!values ∪ $data);
    self
}


