package Uploader::ThreadManager;
use threads;
use threads::shared;
use Thread::Queue;
use strict;
use base qw/Uploader::Object/;

__PACKAGE__->mk_accessors(qw/
    thumb_dir
    resized_dir
    worker
    thread
    thread_queue
    progress_event
    done_event
    event_handler
    batch_end_event
/);


sub Init {
    my ( $self, $params ) =@_;


    $self->worker(
        $self->new_worker
    );

    $self->thread_queue(
        Thread::Queue->new()
    );

    # worker starts when receiving data from the resize queue
    # resize data must be sent to the calling $handler because $handler data
    # cannot be updated inside the thread
    $self->thread(
        threads->create(
            $self->worker_coderef,
            $self->event_handler,
            $self->worker,
            $self->thread_queue
        )
    );
}


sub worker_coderef {
    my ( $self ) = @_;

    sub { 
        my ( $handler, $worker, $queue ) = @_;
        while (my $data = $queue->dequeue ) {
            
            return 1 if 'STOP' eq $data;
            if('CANCEL' eq $data){
                # remove pending
                while($queue->pending){
                    # must check if valid $image hash
                    $worker->cancel_image(
                        $queue->dequeue
                    );
                }
            }
            elsif('BATCH_END' eq $data->{event}){
                $worker->post_image_event(
                    $self->batch_end_event,
                    $data,
                );
            }
            else{
                $worker->process_image( 
                    $handler,
                    $self->progress_event,
                    $self->done_event,
                    $data
                );
            }
        }
    }
}


sub add_images {
    my ( $self, $images ) = @_;

    $self->thread_queue->enqueue(
        map { shared_clone($_) }@$images
    );
}


sub stop {
    my ( $self ) = @_;

    my $data : shared = "STOP";

    $self->thread_queue->insert(0,$data)
        if defined $self->thread_queue;

    $self->thread->detach;
}


sub pending {
    my ( $self ) = @_;

    $self->thread_queue->pending;
}


sub cancel {
    my ( $self ) = @_;

    my $data : shared = "CANCEL";

    $self->thread_queue->insert(0,$data)
        if defined $self->thread_queue;
}

1;