The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Data::Range::Compare::Stream::Iterator::Compare::LayerCake;


use strict;
use warnings;

use base qw(Data::Range::Compare::Stream::Iterator::Compare::Asc);

sub new {
  my ($class,%args)=@_;
  %args=(ignore_empty=>0,,%args);
  my $self=$class->SUPER::new(%args);

  return $self;
}

sub get_next {
  my ($self)=@_;

  if(defined($self->{filter})) {
    my $result=$self->{next_result};
    delete $self->{next_result};
    return $result;
  }

  if($self->{ignore_full}) {
    my $result=$self->{next_result};
    delete $self->{next_result};
    return $result;
  }

  return $self->SUPER::get_next unless $self->{ignore_empty} or $self->{empty_only};



  my $result=$self->SUPER::get_next;

  while($result->is_empty and $self->has_next) {
    $result=$self->SUPER::get_next;
  }

  return $result;

}

sub prepare  { 
  my ($self)=@_;

  return if $self->prepared;

  $self->SUPER::prepare;
  if(defined($self->{filter})) {
    my $filter=$self->{filter};


    while($self->SUPER::has_next) {
      my $result=$self->SUPER::get_next;
      if($filter->($result)) {
        $self->{next_result}=$result;
	return 1;
      }
    }
    delete $self->{next_result};
    return 0;

  }

}

sub has_next {
  my ($self)=@_;

  $self->prepare;
  
  if(defined($self->{filter})) {
    my $filter=$self->{filter};

    return 1 if defined($self->{next_result});


    while($self->SUPER::has_next) {
      my $result=$self->SUPER::get_next;
      if($filter->($result)) {
        $self->{next_result}=$result;
	return 1;
      }
    }
    delete $self->{next_result};
    return 0;

  } elsif($self->{ignore_full}) {
    return 1 if defined($self->{next_result});

    return 0 unless $self->SUPER::has_next;

    my $result=$self->SUPER::get_next;
    while($result->is_full) {

      return 0 unless $self->SUPER::has_next;
      $result=$self->SUPER::get_next;

    }

    $self->{next_result}=$result;
    return defined($result) ? 1 : 0;

  } else {
    
    # back off and use the parrent class internals
    return $self->SUPER::has_next;
  }


}

1;