package Data::Queue;

=head1 NAME

Data::Queue - Order/Unordered stack


  use Data::Queue;

  my $stack=new Data::Queue;

  my $id=$stack->add($job);

  while($stack->has_next) {
    my ($id,$job)=$stack->get_next;


Stack, with the ablity to add and remove elements by id on the fly. Elements go in and out of the stack in the id order.


use Modern::Perl;
use Moo;
use Data::Result;
use namespace::clean;
our $VERSION='1.0002';

with 'Data::Result::Moo';

sub BUILD {
  my ($self,$args)=@_;
  my $data={};

=head1 OO Methods

=over 4

=item * my @ids=$stack->add(@list)

Adds a list of objects onto the stack


  @ids:  List of ids relative to @list
  @list: List of elements to put on the stack


sub add {
  my ($self,@list)=@_;

  my @result;
  my $list=$self->{list};
  foreach my $obj (@list) {
    my $set=[$self->{id},$obj];

    push @{$self->{stack}},$self->{id};
    push @result,$self->{id};


=item * my ($id,$value)=$stack->get_next

Returns the next id=>value pair from the set.


sub get_next {
  my ($self)=@_;
  my $id=shift @{$self->{stack}};
  my $set=delete $self->{data}->{$id};

  return wantarray ? @{$set} : $set->[1];

=item * if($stack->has_next) { ... }

Returns a Data::Result object, when true, it is safe to call $stack->get_next


sub has_next {
  my ($self)=@_;
  return $#{$self->{stack}}==-1 ?
    $self->new_false("No elements left on the stack!") :
    $self->new_true("yes we have more");

=item * if($self->has_id($id)) { ... }

Returns a Data::Result object:

  When true:  it contains the object from the stack
  When false: it contains an error message


sub has_id {
  my ($self,$id)=@_;

  my $result=$self->new_false('Object Not on stack');
  if(exists $self->{data}->{$id}) {
  return $result;

=item * my $id=$stack->add_by_id($id=>$obj);

Adds the element pair to the stack, with a given id, if the id existed the old element is removed.


sub add_by_id {
  my ($self,$id,$value)=@_;

  $self->{id}=$id if $id >$self->{id};
  my $stack=$self->{stack};

  if($#{$stack}==-1) {
  } elsif($stack->[0] > $id) {
    unshift @{$stack},$id;
  } elsif($stack->[0]==$id) {
    # do nothing!
  } elsif($stack->[$#{$stack}] < $id) {
    push @{$stack},$id;
  } elsif($stack->[$#{$stack}] == $id) {
    # do nothing!
  } else {
  return $id;

=item * $stack->remove($id)

Removes the $id from the stack


sub remove {
  my ($self,$id)=@_;
  delete $self->{data}->{$id};

=item * $self->rebuild_stack

Internal method for rebuilding the internal stack as needed.


sub rebuild_stack {
  my ($self)=@_;
  my @set=sort { $a->[0] <=> $b->[0] } values %{$self->{data}};
  foreach my $set (@set) {
    push  @{$self->{stack}},$set->[0];

=item * my $total=$stack->total

Returns the total number of elements on the stack


sub total {
  my ($self)=@_;
  return scalar(keys %{$self->{data}});


=head1 AUTHOR

Mike Shipper Mike Shipper <AKALINUX@CPAN.ORG>