$Tk::Interpolator::VERSION = '1.0';

package SITk::Interpolator;

use Tk::widgets qw/Pane LabFrame Label Entry/;
use base qw/Tk::Derived Tk::Frame/;
use strict;
use Checkbarcode2;
use Carp;

use SITk::BarcodeEntry;

use constant TRUE  => 1;
use constant FALSE => 0;

Construct Tk::Widget 'Interpolator';


sub ClassInit {
    my ($class,$mw) = @_;
    $class->SUPER::ClassInit($mw);
}


sub Populate {
    my ($self,$args) = @_;

    my $pane = $self->Scrolled('Pane',
			       -scrollbars=>'osoe',
			       -bg=>'red',
			       )->pack(-fill=>'both',-expand=>1)->Subwidget('pane');

    my $frame1 = $pane->LabFrame(-label     => 'Basic Interpolation',
				 -labelside => 'acrosstop',
				 )->pack(-fill=>'x',-expand=>1,-pady=>10,-padx=>10);

    my $frame2 = $pane->LabFrame(-label     => 'Sequential Interpolation',
				 -labelside => 'acrosstop',
				 )->pack(-fill=>'x',-expand=>1,-pady=>10,-padx=>10);

    $self->_buildBasicFrame($frame1);
    $self->_buildSequenceFrame($frame2);
    
    $self->SUPER::Populate($args);

    $self->ConfigSpecs(-state => [[$self->{numericFrame}->Subwidget('frame')->children(),
				   $self->{alphabeticFrame}->Subwidget('frame')->children(),
				   $self->{barcodeFrame}->Subwidget('frame')->children(),
				   $self->{textFrame}->Subwidget('frame')->children()],'state','State']);
}

sub _buildBasicFrame {
    my ($self,$frame) = @_;
    my $text;
    $self->{textFrame} = 
	$frame->LabFrame(-label=>'Text',
			 -labelside => 'acrosstop')
	->pack(-fill  => 'x',
	       -pady  => 1,
	       -padx  => 10,
	       -ipady => 10,
	       -ipadx => 10);
    
    $self->{textFrame}->Label(-text=>'Text')
	->grid( $self->{textFrame}->Entry(-width=>20,-textvariable=>\$text),
		$self->{textFrame}->Button(-text=>'Clear',-command=>sub {
		    foreach($self->{textFrame}->Subwidget('frame')->children()) {
			if($_->isa('Tk::Entry')) { $_->delete(0,'end'); }
		    }}),
		$self->{textFrame}->Button
		(-text=>'Go',-command=>sub { $self->_textGo($text);}),-padx=>5);

}


sub _buildSequenceFrame {
    my ($self,$frame) = @_;

    foreach my $labFrameName (qw/numeric alphabetic barcode/) {
	no strict 'refs';
	my $annonSub = \&{"_".$labFrameName."Go"};
	my $key      = $labFrameName . "Frame";
	
	$self->{$key} = $frame->LabFrame
	    (-label     => ucfirst($labFrameName),
	     -labelside => 'acrosstop'
	     )->pack(-fill   => 'x',
		     -expand => 1,
		     -pady   => 10,
		     -padx   => 10,
		     -ipady  => 10,
		     -ipadx  => 10);
	
	my $entryType = $key eq 'barcodeFrame' ? "BarcodeEntry" : "Entry";

	$self->{$key}->Label(-text => 'Start')
	    ->grid($self->{$key}->$entryType
		   (-width=>15,
		    -textvariable=>\$self->{$labFrameName}{start}),
		   $self->{$key}->Label(-text=>'End'),
		   $self->{$key}->$entryType
		   (-width=>15,
		    -textvariable=>\$self->{$labFrameName}{stop}),
		   $self->{$key}->Button
		   (-text=>'Clear',-command=>sub{ 
		       foreach($self->{$key}->Subwidget('frame')->children()) {
			   if($_->isa('Tk::Entry')) { $_->delete(0,'end'); }
		       }}),
		   $self->{$key}->Button
		   (-text=>'Go',-command=>[$annonSub,
					   $self,
					   $self->{$labFrameName}]),-padx=>5);

	#if($labFrameName eq 'barcode') {
	#    foreach my $widget ($self->{$key}->Subwidget('frame')->children()) {
	#	if($widget->isa('Tk::Entry')) {
	#
	#	    #$widget->bind('<Return>'=>sub{
	#	    #	my $data = $widget->get();
	#	    #	return unless $data;
	#	    #	my $validate = Verifynumber($data);
	#	    #	$widget->Tk::Error("ERROR: barcode is not valid.",
	#	    #			   "The barcode id is not valid or recognised by this widget.")
	#	    #	    unless $validate->{Process} eq 'Good';
	#	    #	$widget->delete(0,'end');
	#	    #	$widget->insert(0,$validate->{Whole});
	#	    #});
	#	}
	#    }
	#}
    }
}


sub _textGo {
    my ($self,$textVar) = @_;
    return unless $textVar;
    my @data=();
    foreach(@{$self->{_interpolateTo}}) { push(@data,$textVar); }
    $self->_insertData(\@data);
}


sub _numericGo {
    my ($self,$var) = @_;
    return unless defined $var->{start} && defined $var->{stop};
    my @result=();
    my $start = $var->{start};
    my $stop  = $var->{stop};
    $self->_insertData(_interpolate($var->{start},$var->{stop}));
}


sub _alphabeticGo {
    my ($self,$var) = @_;
    return unless $var->{start} && $var->{stop};
    my @alpha = (qw/a b c d e f g h i j k l m n o p q r s t u v w x y z/);
    my (%temp,@result,$isUpperCase);
    foreach(keys(%{$var})) {
	$isUpperCase = ($var->{$_} =~ /^[A-Z]/) ? TRUE : FALSE;
	for(my $i=0; $i < scalar(@alpha); $i++) {
	    if(lc($var->{$_}) eq $alpha[$i]) {
		$temp{$_} = $i;
		last;
	    }
	}
	croak "ERROR: $var->{$_} is not alphabetic." unless defined $temp{$_};
    }
    foreach my $res (@{_interpolate($temp{start},$temp{stop})}) {
    	push(@result,$isUpperCase ? uc($alpha[$res]) : $alpha[$res]);
    }
    $self->_insertData(\@result);
}


sub _barcodeGo {
    my ($self,$var) = @_;
    return unless $var->{start} && $var->{stop};
    my ($prefix1,$start) = $var->{start} =~ /(\w\w)(\d+)\w$/;
    my ($prefix2,$stop ) = $var->{stop}  =~ /(\w\w)(\d+)\w$/;
    croak "ERROR: barcode prefix types must be the same." unless $prefix1 eq $prefix2;
    my @data=();
    foreach(@{_interpolate($start,$stop)}) {
	push(@data,makeID($prefix1 . $_));
    }
    $self->_insertData(\@data);
}


sub _insertData {
    my ($self,$interpolateData) = @_;
    return unless $self->{_interpolateTo};
    for(my $i=0; $i < scalar(@{$interpolateData}); $i++) {
	if(exists($self->{_interpolateTo}[$i]) && 
	   $self->{_interpolateTo}[$i]->isa('Tk::Entry')) {
	    $self->{_interpolateTo}[$i]->insert('end',$interpolateData->[$i]);
	}else{
	    last;
	}
    }
}


sub _interpolate {
    my ($start,$stop) = @_;
    my @result; push(@result,$start);
    until($start == $stop) {
    	if($start < $stop) { $start++; }
    	if($start > $stop) { $start--; }
    	push(@result,$start);
    }
    return \@result;
}


sub setInterestedWidgets {
    my ($self,$interpolateTo) = @_;
    $self->{_interpolateTo} = $interpolateTo;
}





1;
