#!/usr/bin/perl
use strict;
use warnings;
use Tk;
use Tk::Photo;
use Tk::PNG;
use Tk::JPEG;
use Data::Dumper qw/Dumper/;
use File::Basename;
#use File::Spec;
use Image::Size;
use Text::CSV_XS;
use feature "say";
my ($base_filename,$overlay_directory,$current_image,@overlays,@contents,$print_dir,$loadfile);
my @dir_stack = ('.');
my $word="";
my $image_width=0;
my $image_height=0;
my $canvas;
my $click=0;
my $cp=0;
my $ct=0;
my @points;

my $colour_file="fewer_colours";
my %colours;
my $colour;
my $csv = Text::CSV_XS->new ();
open (my $fh , '<',"$colour_file")or die"$!";		
while (my $line = <$fh>) {
      $csv->parse($line);
      %colours=$csv->fields();
}
close $fh;
$csv=undef;
say $colours{2};

&check_last;
my $msg="save points path $cp";
my $mw14 = MainWindow->new;
$mw14->geometry("800x1000+1100+1100");
$mw14->title("Place overlays on an image");
$mw14->Label(-font => '{Helvetica} 20', -width =>50, -text => "Make sure base image is called something sensible\n as everything gets called that.\nEverything in overlay directory is loaded as an overlay.\nClick one overlay to select it's directory.\nSelect overlay directory with one small image\nto just make files of point positions.\nSave selections saves base in first line of csv.\nLast points saved is in points.txt \npoints paths saved in \"tracks\" directory ")->grid(qw/ -row 2 -column 0 -columnspan 2 -sticky n/);
$mw14->Button(-font => '{Helvetica} 20', -width =>20, -text => "select base image", -command => sub{$word="base";&refresh_listbox()})->grid(qw/ -row 4 -column 0 -sticky n/);
$mw14->Button(-font => '{Helvetica} 20', -width =>20, -text => "select overlays", -command => sub{$word="overlays";&refresh_listbox()})->grid(qw/ -row 4 -column 1 -sticky n/);

$mw14->Button(-font => '{Helvetica} 20', -width =>20, -text => "add points paths", -command => sub{&make_track()})->grid(qw/ -row 13 -column 0 -sticky n/);
$mw14->Button(-font => '{Helvetica} 20', -width =>20, -textvariable => \$msg, -command => sub{&save_points;})->grid(qw/ -row 13 -column 1 -sticky n/);

$mw14->Button(-font => '{Helvetica} 20', -width =>20, -text => "load file", -command => sub{$word="load";&refresh_listbox()})->grid(qw/ -row 12 -column 0 -sticky n/);
$mw14->Button(-font => '{Helvetica} 20', -width =>20, -text => "save selections", -command => sub{&save})->grid(qw/ -row 12 -column 1 -sticky n/);

$mw14->Button(-font => '{Helvetica} 20', -width =>20, -text => "check", -command => sub{say "check";})->grid(qw/ -row 18 -column 0 -sticky n/);
$mw14->Button(-font => '{Helvetica} 20', -width =>20, -text => "exit", -command => sub{$mw14->destroy;})->grid(qw/ -row 18 -column 1 -sticky n/);
#$mw14->Label(-font => '{Helvetica} 20', -width =>15, -text => " ")->grid(qw/ -row 19 -column 0 -columnspan 2 -sticky n/);
my $frame = $mw14->Frame()->grid(qw/ -row 20 -column 0 -sticky n/);;

my $listbox = $frame->Scrolled('Listbox', -font => '{Helvetica} 20', -scrollbars => 'se')->grid(qw/ -row 0 -column 0 -sticky n/);
$listbox->bind('<Double-Button-1>', \&select_item);
my $up_button = $frame->Button(-font => '{Helvetica} 15', -text => 'UP', -command => \&go_up)->grid(qw/ -row 1 -column 0 -sticky n/);
#$mw14->Label(-font => '{Helvetica} 20', -width =>15, -text => "-------------------")->grid(qw/ -row 28 -column 0 -sticky n/);
$mw14->Button(-font => '{Helvetica} 20', -width =>20, -text => "reset counter", -command => sub{$cp=0;$msg="save points path $cp";})->grid(qw/ -row 19 -column 0 -sticky n/);
$mw14->Label(-font => '{Helvetica} 20', -width =>10, -text => "points ")->grid(qw/ -row 19 -column 1 -sticky n/);
$mw14->Label(-font => '{Helvetica} 30', -width =>5, -textvariable => \$click)->grid(qw/ -row 20 -column 1 -sticky n/);

MainLoop;

sub screen{
say "screen";
my ($overlay_directory,$base_filename) =@_;
my @photos;
my @display;
#my @contents;
say"directory is $overlay_directory\n";
#@contents = grep { !/^\.{1,2}$/ } @contents;  # Remove "." and ".." entries	
#@contents = sort numerically @contents;
#say Dumper @contents;
#don't do it if $overlay[] exists because we loaded it.
if(!@overlays){
@contents = grep { !/^\.{1,2}$/ } @contents;  # Remove "." and ".." entries	
@contents = sort numerically @contents;	
for (my $i=0;$i<=$#contents;$i++){	
$overlays[$i]{image}=$overlay_directory."/".$contents[$i];
#$photos[$i]=$window2->Photo(-file =>$overlays[$i]{image});	
#$display[$i]=$canvas->createImage(0, 0, -anchor => 'nw', -image => $photos[$i]);	
}
}
#say Dumper @overlays;
#exit;

my ($x,$y)=imgsize($base_filename);	
$image_width=$x;
$image_height=$y;
my $window2 = $mw14->Toplevel;
$window2->geometry($x."x".$y."+1500+500");
$canvas = $window2->Canvas(-width => $x, -height => $y)->grid(qw/ -row 0 -column 0 -sticky n/);
my $base_image=$window2->Photo(-file =>$base_filename);
my $display=$canvas->createImage(0, 0, -anchor => 'nw', -image => $base_image);
$current_image=2;
my ($prevX, $prevY);

for (my $i=0;$i<=$#overlays;$i++){
if(!$overlays[$i]{x}){$overlays[$i]{x}=0;$overlays[$i]{y}=0;		
$photos[$i]=$window2->Photo(-file =>$overlays[$i]{image});	
$display[$i]=$canvas->createImage($overlays[$i]{x}, $overlays[$i]{y}, -anchor => 'nw', -image => $photos[$i]);	
}
else{
my ($x,$y)=imgsize($overlays[$i]{image});
$photos[$i]=$window2->Photo(-file =>$overlays[$i]{image});	
my $x1=$overlays[$i]{x}-($x/2);
my $y1=$overlays[$i]{y}-($y/2);
$display[$i]=$canvas->createImage($x1, $y1, -anchor => 'nw', -image => $photos[$i]);	
}
}

$canvas->Tk::bind('<Button-1>', sub {
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
    my @items = $canvas->find('withtag', 'current'); # Get item under pointer
   
    if (@items) {
        $current_image = $items[0]; # Select the topmost item under the pointer
        if($current_image<2){$current_image=2}
($prevX, $prevY) = ($x, $y); # Store the current mouse position
}
});
$canvas->Tk::bind('<B1-Motion>', sub {
 my ($x, $y) = ($Tk::event->x, $Tk::event->y);
    my $dx = $x - $prevX;
    my $dy = $y - $prevY;
    $canvas->move($current_image, $dx, $dy);# if defined $current_item;
   ($prevX, $prevY) = ($x, $y);
});	
# Bind mouse button release to print positions
$canvas->Tk::bind('<ButtonRelease-1>', sub {
   # return unless defined $current_image;
    
    # Get the final position of the object
    my ($objX, $objY) = $canvas->coords($current_image);
    my ($obj_width,$obj_height)=imgsize($overlays[0]{image});
    say "overlay width is $obj_width";
    say "current image is $current_image";
    my $num=$current_image -2;
   # Get the current mouse position
   # my ($x, $y) = ($Tk::event->x, $Tk::event->y);

    # Print out the positions
    print "Object position: ($objX, $objY)\n";
   # print "Mouse position: ($x, $y)\n";
   $objX=$objX+($obj_width/2);
   $objY=$objY+($obj_height/2);
   $overlays[$num]{x}=$objX;
   $overlays[$num]{y}=$objY;
    undef $current_image;

});	
}
	
sub refresh_listbox {

    my $dir = $dir_stack[-1];

    $listbox->delete(0, 'end');

    opendir(my $dh, $dir) or die "Can't open $dir: $!";
    @contents = readdir($dh);
    closedir($dh);
    foreach my $item (@contents) {
      
        next if $item =~ /^\./;  # skip hidden files/directories

        my $path = File::Spec->catfile($dir, $item);
        
        if (-d $path) {
            $listbox->insert('end', $item);
            $listbox->itemconfigure('end', -foreground => 'blue');  # Apply blue color to directory item
        } else {
            $listbox->insert('end', $item);
        }
       
        if ($item =~ /\.png$/i || $item =~ /\.jpg$/i){
		   $listbox->itemconfigure('end', -foreground => 'Maroon');
		   }
		  
    }

}

sub select_item {
say $word;
if($base_filename && $overlay_directory){say "got two";&screen($overlay_directory,$base_filename)}
my $selected_file;
    my $selection = $listbox->get('active');
 my $path = File::Spec->catfile($dir_stack[-1], $selection);

    if (-d $path) {
    $selected_file = $path;
        print "Selected directory: $selected_file\n";  # Print the selected directory
        push @dir_stack, $path;  # Push selected directory to the stack
        refresh_listbox();
       $print_dir =$path;
       if ($word eq "overlays"){say "overlay";$overlay_directory=$print_dir;};    
    } elsif (-f $path) {
#} elsif ($print_dir =~ /\.png$/i || $print_dir =~ /\.jpg$/i||/\.list/i){
            $listbox->insert('end', $path);
        if ($word eq "base"){say "base";$base_filename=$path;};
        if ($word eq "load"){$loadfile=$path;&load($loadfile)};     
        }
 
    }


sub select_base{
	}







sub go_up {
    pop @dir_stack if @dir_stack > 1;  # Pop the top directory from the stack if not already at the root
    refresh_listbox();
}

sub save{
$msg="save points path ".$cp;
my $text="$overlay_directory".".list";
open(my $fh, '>', "$text") or die "Could not open file". "$text $!";
print $fh "base,$base_filename,overlays,$overlay_directory\n";
for( my $i=0;$i<=$#overlays;$i++){
print $fh "image,$overlays[$i]{image},x,$overlays[$i]{x},y,$overlays[$i]{y}\n";
}
close $fh;	
say "saved $text";
}

sub numerically {
    my ($a_num) = $a =~ /(\d+)/;
    my ($b_num) = $b =~ /(\d+)/;
$a_num //= 0;  # Set $a_num to 0 if it's uninitialized
$b_num //= 0;  # Set $b_num to 0 if it's uninitialized
return $a_num <=> $b_num;
}

sub load{
# this is th intial position of base _image and overlays.
my $csv = Text::CSV_XS->new ();
$loadfile=$_[0];
say "file = $loadfile";	
my $ct=0;
open ( my $fh , '<',"$loadfile")or die"$!";		
while (my $line = <$fh>) {
#chomp $line; 
# If it's the first line, store it in the hash
    if ($. == 1) {
         #my %values = split /,/, $line;
         $csv->parse($line);
         my %values=$csv->fields();
$base_filename=$values{base};
$overlay_directory=$values{overlays};
say " base is $base_filename  overlay directory is $overlay_directory";
    } else {
        # Otherwise, store it in the array
      $csv->parse($line);
      my %values2=$csv->fields();
     #my %values2 = split /,/, $line;
    $overlays[$ct]{image}=$values2{image};
    $overlays[$ct]{x}=$values2{x};
 
    $overlays[$ct]{y}=$values2{y};
    $ct++;
    }
}
say Dumper @overlays;
close $loadfile;
$csv=undef;
say "base= $base_filename";
#exit;
#say Dumper@overlays;
&screen($overlay_directory,$base_filename);	
}


sub make_track{
#$canvas->Tk::unbind('<Button-1>');
# Bind mouse button-1 press event to handle_click function
$canvas->Tk::bind('<ButtonRelease-1>', sub {});
$canvas->Tk::bind('<B1-Motion>', sub {});
$canvas->Tk::bind('<Button-1>', sub {
    my $event = $canvas->XEvent;
    my ($x, $y) = ($event->x, $event->y);
    handle_click($x, $y);
});
}
	
sub handle_click {
    my ($x, $y) = @_;

#say "$colours{$ct}";

# Print the mouse pointer coordinates relative to the Canvas centre
$points[$cp][$click]{x}=$x-($image_width/2);
$points[$cp][$click]{y}=$y-($image_height/2);
    # Draw a dot at the clicked location on the Canvas
    #$canvas->createOval($x-3, $y-3, $x+3, $y+3, -fill => 'red');
#my $k=keys %colours;
# for (my $i=0;$i<=$k;$i++){
#$colour=$colours{$i};
$points[$cp][$click]{x}=int($points[$cp][$click]{x});
$points[$cp][$click]{y}=int($points[$cp][$click]{y});
 $canvas->createOval($x-3, $y-3, $x+3, $y+3, -fill => $colour);
#say "**********$points[$cp][$click]{x}=$x-($image_width/2)";
$click++;
#say $i;
#}
}


sub save_points{
if(! -d "tracks"){mkdir "./tracks"}
my ($file,$directories,$suffix) = fileparse($base_filename, qr/\.[^.]*$/);###########
say "$file $directories $suffix"; 
#my $save_file= join "_",$file,"paths.list";
say "click  $click cp $cp";;
my $save_file= join "_","tracks/$file","paths$cp.list";
my $l=@{$points[$cp]}; 
open ($fh , '>',"$save_file")or die"$!";
for(my $i=0;$i<=($l-1);$i++){
print $fh "x,$points[$cp][$i]{x},y,$points[$cp][$i]{y}\n";
}
close $fh;
#my @words= split /\//,$directories;# split directory path on "/"
say Dumper @points;
say "here save";
my $k=keys %colours;
my $rn = int(rand($k));
#print $rn, "\n";
$colour=$colours{$rn};
say $colours{$rn};	
$cp++;
$click=0;
$msg="save points path ".$cp;
open (my $fh2 , '>',"points.txt")or die"$!";
print $fh2 "point,$cp";


}

# MainLoop;
sub check_last{
my $last_point;
if(! -d "points"){mkdir "./points"}
open ($fh , '<',"points.txt")or die"$!";
my $csv = Text::CSV_XS->new ();		
while (my $line = <$fh>) {
      $csv->parse($line);
      my %values=$csv->fields();
$last_point=$values{point};
}
close $fh;
#my $last_point=$values{point};
say "last point= $last_point";
$cp=$last_point;
return;	
}
