package DX::Types;

use strictures 2;
use Type::Library
  -base,
  -declare => (
    (our @CLASSES = qw(
      Hypothesis Scope ResolvedPropositionSet Proposition DependencyMap
      PropositionSequence QueryState ShellState ShellSession SearchState
      ResolutionSpace ResolutionStrategy Resolution Expander SearchProcess
    )),
    (our @ROLES = qw(
      Step Action ActionPolicy Predicate Value ActionBuilder Update
    )),
    qw(
      DependencyType _DependencyTree DependencySpec
      One DependencyGroupEntry DependencyGroup ValuePath
      EventType ApertureList DependencyList ShellMode
    ),
  )
;
use Type::Utils -all;
use Types::Standard qw(
  ArrayRef Tuple HashRef Dict Maybe Optional slurpy Str Enum
);
use DX::Utils qw(:event_types :dep_types);

foreach my $class (our @CLASSES) {
  class_type $class => { class => 'DX::'.$class };
}

foreach my $role (our @ROLES) {
  role_type $role => { role => 'DX::Role::'.$role };
}

class_type DictValue => { class => 'DX::Value::Dict' };

declare ValuePath => as ArrayRef[Str];

declare PropositionList => as ArrayRef[Proposition];

declare DecisionList => as ArrayRef[Tuple[ResolutionSpace, SearchState]];

declare DependencyType => where {
  foreach my $cand (EXISTENCE_OF, TYPE_OF, INDICES_OF, CONTENTS_OF) {
    return 1 if $_ eq $cand;
  }
  return 0;
};

declare EventType => where {
  foreach my $cand (VALUE_SET, VALUE_EXISTS) {
    return 1 if $_ eq $cand;
  }
  return 0;
};

declare _DependencyTree => where { is_DependencyTree($_) };

declare DependencySpec => as Tuple[DependencyType, slurpy ValuePath];

declare DependencyList => as ArrayRef[DependencySpec];

declare One => where { !ref($_) and $_ eq 1 };

declare DependencyTree => # [ \%subtree, \%existence_of, ... ]
  as HashRef[Tuple[
       Maybe[_DependencyTree],
       (Optional[Maybe[HashRef[One]]]) x 4
     ]];

declare ApertureList => as ArrayRef[Tuple[EventType, slurpy ValuePath]];

declare ShellMode => as Enum[qw(shell query)];

## These were from the dependency group thing which makes no sense until
## we have scoping, so revisit it then
#
#declare DependencyGroupEntry =>
#  as Tuple[DependencyType, slurpy ArrayRef[Value|Str]];
#
#declare DependencyGroup =>
#  as Tuple[Maybe[Value], slurpy ArrayRef[DependencyGroupEntry]];
#
#declare DependencyGroupList => as ArrayRef[DependencyGroup];

1;
