#!/usr/bin/perl
use strict;
use diagnostics;
use warnings;
use feature "say";
use Math::Trig;
use Tk;
use Tk::PNG;
use Tk::JPEG;
use Text::CSV qw(csv);
use Image::Imlib2;
use Data::Dumper qw(Dumper);
my %scene;
my @contents;
my @overlays;
my @dir_stack="./";
my $print_dir;
my $dir;
my $path;
my $word="x";
my $group;
my @level;
my $levels_directory="./";
$scene{scene_length}=100;
$scene{scene_name}="TEST";
$scene{bg}="./BLANK.png";
$scene{canvas_width}=916;
$scene{aspect}=1;

my $mw6 = MainWindow->new(-title => "CONSTRUCT DOPESHEET");
my $font = $mw6->fontCreate(
#Courier,Times,Helvetica,Arial
  -family=>"Helvetica",
  -size => 14,
  -weight => "normal");
my $w=$mw6->screenwidth;
my $h=$mw6->screenheight;
my $w_unit=int($w*.05);my $h_unit=int($h*.05);
my $sx=$w_unit*7;my $sy=$h_unit*10;my $px=$w_unit*4;my $py=$h_unit*5;
$mw6->geometry(($sx)."x".($sy)."+".($px)."+".($py));

my $string="\nThe levels directories need to contain files of lists with image,w,h,x,y per frame.\n One file, with \".list\" suffix, for each overlay.\nEach level directory must contain at least one file.\nRun \"load_and_position_combined\", for the overlay position and tracks.\nRun \"make_lists_from_directory\" for making lists, merging x.y with image, w,h.\nSelect background \"BLANK.png\" for making transparent overlays.\nif \"BLANK.png\" must say canvas width and aspect.";

my $frame = $mw6->Frame()->grid(qw/ -row 0 -column 0 -columnspan 10 -sticky w/); 
my $entry = $frame->Label(-font => '{Helvetica} 22', -justify => 'left',  -textvariable => \$string)->grid(qw/ -row 0 -column 0 -columnspan 8 -sticky w/); 
$mw6->Label(-font => $font, -text => "SELECT")->grid(qw/ -row 1 -column 4 -sticky n/);
#$mw6->Label(-font => $font, -text => "")->grid(qw/ -row 2 -column 0 -sticky n/);
$mw6->Label(-font => $font, -text => "Length")->grid(qw/ -row 1 -column 6 -sticky n/);
$entry = $mw6->Entry(-font => $font, -textvariable => \$scene{scene_length}, -width =>8)->grid(qw/ -row 2 -column 6 -sticky w/);

$mw6->Label(-font => $font, -width =>20,-text => "Canvas width pxls ")->grid(qw/ -row 2 -column 0 -sticky w/);
$entry = $mw6->Entry(-font => $font, -width =>10,-textvariable => \$scene{canvas_width})->grid(qw/ -row 2 -column 1 -sticky w/);
$entry = $mw6->Button(-font => $font, -text => "Scene Directory", -width =>20, -command => sub{&check_dir;$word="scene";&refresh_listbox()})->grid(qw/ -row 2 -column 4 -sticky w/);
$entry = $mw6->Entry(-font => $font, -width =>20, -textvariable => \$scene{scene_name})->grid(qw/ -row 2 -column 5 -sticky w/);

$mw6->Label(-font => $font,-width =>20, -text => "Canvas aspect ratio ")->grid(qw/ -row 3 -column 0 -sticky w/);
$entry = $mw6->Entry(-font => $font,-width =>10, -textvariable => \$scene{aspect})->grid(qw/ -row 3 -column 1 -sticky w/);
$entry = $mw6->Button(-font => $font, -text => "Background image", -width =>20, -command => sub{$word="bg";&refresh_listbox()})->grid(qw/ -row 3 -column 4 -sticky w/);
$entry = $mw6->Entry(-font => $font, -state => 'disabled',-width =>20, -textvariable => \$scene{bg})->grid(qw/ -row 3 -column 5 -sticky w/);
my $button=$mw6->Button(-font => $font, -text => "X", -width =>2, -command => sub {$scene{bg}="";})->grid(qw/ -row 3 -column 7 -sticky w/);

$entry = $mw6->Button(-font => $font, -text => "camera whxy file", -width =>20, -command => sub{$word="camera";&refresh_listbox()})->grid(qw/ -row 4 -column 4 -sticky w/);	
$entry = $mw6->Entry(-font => $font, -state => 'disabled',-width =>20, -textvariable => \$scene{camera_whxy})->grid(qw/ -row 4 -column 5 -sticky w/);


$mw6->Label(-font => $font, -text => "")->grid(qw/ -row 5 -column 0 -sticky n/);
$button=$mw6->Button(-font => $font, -text => "X", -width =>2, -command => sub {$scene{camera}="";})->grid(qw/ -row 4 -column 7 -sticky w/);

$button = $mw6->Button(-font => $font, -text => "Apply Camera Move", -width =>15, -command => sub {&apply_camera(0);})->grid(qw/ -row 4 -column 6 -sticky w/);

$button=$mw6->Button(-font => $font, -text => "Level 0 SOURCE dir", -width =>20, -command => sub{$word="levels";$group=0;&refresh_listbox()})->grid(qw/ -row 6 -column 4 -sticky w/);
$entry = $mw6->Entry(-font => $font, -state => 'disabled', -width =>20,-textvariable => \$level[0]{list_dir})->grid(qw/ -row 6 -column 5 -sticky w/);
$button = $mw6->Button(-font => $font, -text => "Make Array Level 0", -width =>15, -command => sub {&make_levels(0);})->grid(qw/ -row 6 -column 6 -sticky w/);
$button=$mw6->Button(-font => $font, -text => "X", -width =>2, -command => sub {$level[0]{list_dir}="";})->grid(qw/ -row 6 -column 7 -sticky w/);

$button=$mw6->Button(-font => $font, -text => "Level 1 SOURCE dir", -width =>20, -command => sub{$word="levels";$group=1;&refresh_listbox()})->grid(qw/ -row 8 -column 4 -sticky w/);
$entry = $mw6->Entry(-font => $font, -state => 'disabled', -width =>20,-textvariable => \$level[1]{list_dir})->grid(qw/ -row 8 -column 5 -sticky w/);
$button = $mw6->Button(-font => $font, -text => "Make Array Level 1", -width =>15, -command => sub {&make_levels(1);})->grid(qw/ -row 8 -column 6 -sticky w/);
$button=$mw6->Button(-font => $font, -text => "X", -width =>2, -command => sub {$level[1]{list_dir}="";})->grid(qw/ -row 8 -column 7 -sticky w/);


$button=$mw6->Button(-font => $font, -text => "TEST BLEND", -width =>20, -command => sub{&test_blend})->grid(qw/ -row 12 -column 4 -sticky w/);

$entry = $mw6->Button(-font => $font, -text => "LOAD\n", -width =>7,-command => sub {&search("load",0);})->grid(qw/ -row 4 -column 0    -sticky w/);		

$entry = $mw6->Button(-font => $font, -width =>7,-text =>"SAVE\n", -command => sub{&save_scene})->grid(qw/ -row 4 -column 1 -sticky w/);
$entry = $mw6->Button(-font => $font, -width =>7,-text =>"CLOSE\n", -command => sub{$mw6->destroy;})->grid(qw/ -row 5 -column 1 -sticky w/);
	
my $frame2 = $mw6->Frame()->grid(qw/ -row 16 -column 0 -columnspan 1 -sticky w/); 
my $listbox = $frame2->Scrolled('Listbox', -font => '{Helvetica} 20', -scrollbars => 'se')->grid(qw/ -row 0 -column 0 -sticky w/); 
$listbox->bind('<Double-Button-1>', \&select_item);
my $text="1: select background";
$listbox->insert('end', $text);
$text="2: select level directory";
$listbox->insert('end', $text);
$text="3: make level array";
$listbox->insert('end', $text);
$text="4: blend";
$listbox->insert('end', $text);
my $up_button = $frame2->Button(-font => '{Helvetica} 15', -text => 'UP', -command => \&go_up)->grid(qw/ -row 2 -column 0 -sticky n/); 

MainLoop;
&create_empty_file;

sub create_empty_file{
my $blank_image=Image::Imlib2->new(2,2);
$blank_image->save("BLANK.png");
$blank_image=undef;
}

sub check_dir{
if(! -d $scene{scene_name}){mkdir $scene{scene_name}}
return;	
}

sub test_blend{
#my $lv;
&check_dir;
say "group is $group";
#$group=0;
say $scene{bg};
say Dumper @overlays;	
#say $overlays[0][0][1]{image};
#say $overlays[0][1][1]{image};
#say $overlays[0][2][1]{image};
my $image_bg;
if ($scene{bg}eq "./BLANK.png"){
$scene{height}=$scene{canvas_width}*$scene{aspect};
$image_bg = Image::Imlib2->new_transparent($scene{canvas_width},$scene{height});
}
else{$image_bg = Image::Imlib2->load($scene{bg});}	

my $img_w=$image_bg->width;
my $img_h=$image_bg->height;
my $groups= scalar  @overlays;
#my $frames =scalar $overlays[$group][0];#if add [group] that will be @{$overlays[0][0]}
#my $levels=scalar $overlays[$group]; #if add [group] will be @{$overlays[0]}
for(my $lv=0;$lv<$groups;$lv++){
my $frames =scalar @{$overlays[$lv][0]};#if add [group] that will be @{$overlays[0][0]} This is the size of the first file in the directory
my $levels=scalar @{$overlays[$lv]};
#my $grouping= scalar  @overlays;
say "groups= $groups";
say "frames= $frames";
say "levels= $levels"; 

#my $chk=scalar @levels;
#say "level= $chk";
#say $overlays[0][0][0]{image};
#for (my $f=0;$f<$scene{scene_length}-1;$f++){	
for (my $f=0;$f<$frames;$f++){
my $clone=$image_bg->clone;

for (my $i=0;$i<$levels;$i++){
$overlays[$lv][$i][$f]{image}//="./BLANK.png";
my $image=Image::Imlib2->load($overlays[$lv][$i][$f]{image});
my $over_w=$image->width;
my $over_h=$image->height;
my ($x,$y)=((($img_w-$over_w)/2)+$overlays[$lv][$i][$f]{x}+($over_w/2), (($img_h-$overlays[$lv][$i][$f]{h})/2)+$overlays[$lv][$i][$f]{y}+($over_h/2));
$clone->blend($image, 1, 0, 0 ,$over_w,$over_h,$x,$y,$overlays[$lv][$i][$f]{w},$overlays[$lv][$i][$f]{h});
}
my $name=join "","out",$lv,"%03d.png";
$name = sprintf($name, $f);
my $save_file= join "/",$scene{scene_name},$name;
$clone->save($save_file);
print "x \b";
}
print "\n";	
say "done";
}
}

sub refresh_listbox {
my $dir = $dir_stack[-1];
#$dir = grep { /.png/ } $dir_stack[-1];

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

    opendir(my $dh, $dir) or die "Can't open $dir: $!";
    @contents = readdir($dh);
    closedir($dh);
# Sort @contents alphabetically
    #@contents = sort @contents;
    @contents = sort { lc($a) cmp lc($b) } @contents;
    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
        } elsif ($item =~ /\.png$/i || $item =~ /\.jpg/i || $item =~ /\.list/i ){
            $listbox->insert('end', $item);
        }
    }
}

sub select_item {
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;
        say "Selected directory: $print_dir\n";  # Print the selected directory
   if ($word eq "scene"){$scene{scene_name}=$path;@dir_stack = ('.');}
   if ($word eq "levels"){$level[$group]{list_dir}=$path;@dir_stack = ('.');}
   } elsif (-f $path) {
        #$selected_file = $path;
        if ($word eq "bg"){$scene{bg}=$path;@dir_stack = ('.');}
        if ($word eq "camera"){$scene{camera_whxy}=$path;@dir_stack = ('.');}
    }
refresh_listbox();
}

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 make_levels{
$group=$_[0];
say $scene{scene_name};	
# each level's button is pressed to make its array. 
# directories of lists of levels is $group
my $csv = Text::CSV->new ();
#my $group=$_[0];
my @list;
# @list; # will have the list of files in the directory that contain image,w,h,x,y per frame
my $load_dir=$level[$group]{list_dir};#this is the directory containing the files
opendir(my $dh, $load_dir) or die "Can't open $dir: $!";
my @files = grep { !/^\.\.?$/ } readdir($dh);
closedir($dh);
foreach my $file (@files) {
push @list,$file;# @list contains the files in the group. 
    }
@list=sort numerically @list;
#say Dumper @list;
my $lnum=$#list;# this is the number of animated things in the group
say $lnum;
#exit;
# $group is the grouped overlays in a directory, 
# $i is the overlay,
# $ct is the frame,
for(my $i=0;$i<=$lnum;$i++){
my $ct=0;
open ( my $fh , '<',"$load_dir/$list[$i]")or die"$!";		
while (my $line = <$fh>) {
      chomp $line;
     if( $csv->parse($line)){
      
      my %values=$csv->fields();
     %values = split /,/, $line;
    $overlays[$group][$i][$ct]{image}=$values{image};
    $overlays[$group][$i][$ct]{x}=$values{x};
    $overlays[$group][$i][$ct]{y}=$values{y};
    $overlays[$group][$i][$ct]{w}=$values{w};
    $overlays[$group][$i][$ct]{h}=$values{h};
    $ct++;
    }else {
            # Handle parse errors
            warn "Line could not be parsed: $line\n";
        }
}
close $fh;

}
$csv=undef;	
#say Dumper @overlays;
say "load dir is $load_dir";

	}

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;
}



#    blend (source_image, merge_alpha, sx, sy, sw, sh, dx, dy, dw, dh)
#          (overlay, alpha, rectangle from overlay; position of overlay, scaled w,h)
#    This will blend the source rectangle x, y, width, height from the source_image onto the current image at the destination x, y location
#    scaled to the width and height specified. 
#    If merge_alpha is set to 1 it will also modify the destination image alpha channel, otherwise the  destination alpha channel is left untouched.
#    
#    $image->blend($cropped_image, 0, 0, 0, 50, 50, 200, 0, 50, 50);











































