use strict;
use warnings;

package ASS_Gui;

my @keys = qw[ifname1 ifname2 ifmask ifpad ifstart ifend animdelay animtype animvar animcomment objcount objblocking objvisible objontop objkilling];

use Tk;
use ConfigHandler;

sub new() {
    my $self  = {};
    $self->{"config"} = new ConfigHandler();
    $self->{"config"}->read();
    foreach my $key (@keys) {
        $self->{$key} = $self->{"config"}->{$key};
    }
    bless($self);           # but see below
    return $self;
}

sub startGUI($) {
    my $self = shift;

    # Main Window
    $self->{"main"} = new MainWindow();

    #GUI Building Area
    $self->{"main"} -> Label(-text => "Dateien") -> pack();
    $self->{"frame"} = $self->{"main"} -> Frame() -> pack();
    $self->{"frame"}->gridColumnconfigure(2, -minsize => 400);

    $self->{"ifname1_label"} = $self->{"frame"} -> Label(-text => "Bild-Datei (erste)") -> grid(-row=>1, -column=>1);
    $self->{"ifname1_entry"} = $self->{"frame"} -> Entry(-textvariable => \$self->{"ifname1"}) -> grid(-row=>1, -column=>2, -sticky => "nsew");
    $self->{"ifbutton1"} = $self->{"frame"} -> Button(-text => "..",
                                                    -command => [$self => 'selectInfile1'])
                                            -> grid(-row=>1, -column=>3);

    $self->{"ifname2_label"} = $self->{"frame"} -> Label(-text => "Bild-Datei (letzte)") -> grid(-row=>2, -column=>1);
    $self->{"ifname2_entry"} = $self->{"frame"} -> Entry(-textvariable => \$self->{"ifname2"}) -> grid(-row=>2, -column=>2, -sticky => "nsew");
    $self->{"ifbutton2"} = $self->{"frame"} -> Button(-text => "..",
                                                    -command => [$self => 'selectInfile2'])
                                            -> grid(-row=>2, -column=>3);


    $self->{"parseButton"} = $self->{"main"} -> Button(-text => "Script-Argumente vorschlagen",
                                                    -command => [$self => 'genargs_button'])
                                            -> pack();

    # Spacer
    $self->{"main"} -> Label(-text => " ") -> pack();

    $self->{"main"} -> Label(-text => "Animation") -> pack();
    $self->{"frame2"} = $self->{"main"} -> Frame() -> pack();
    $self->{"ifstart_label"} = $self->{"frame2"} -> Label(-text => "Start:") -> grid(-row=>1, -column=>1);
    $self->{"ifstart_entry"} = $self->{"frame2"} -> Entry(-textvariable => \$self->{"ifstart"}) -> grid(-row=>1, -column=>2, -sticky => "nsew");
    $self->{"ifend_label"} = $self->{"frame2"} -> Label(-text => "Ende:") -> grid(-row=>1, -column=>3);
    $self->{"ifend_entry"} = $self->{"frame2"} -> Entry(-textvariable => \$self->{"ifend"}) -> grid(-row=>1, -column=>4, -sticky => "nsew");
    $self->{"ifpad_label"} = $self->{"frame2"} -> Label(-text => "Padding (Stellenanzahl Nummern):") -> grid(-row=>2, -column=>1);
    $self->{"ifpad_entry"} = $self->{"frame2"} -> Entry(-textvariable => \$self->{"ifpad"}) -> grid(-row=>2, -column=>2, -sticky => "nsew");
    $self->{"ifdelay_label"} = $self->{"frame2"} -> Label(-text => "Delay:") -> grid(-row=>2, -column=>3);
    $self->{"ifdelay_entry"} = $self->{"frame2"} -> Entry(-textvariable => \$self->{"animdelay"}) -> grid(-row=>2, -column=>4, -sticky => "nsew");


    $self->{"ifmask_label"} = $self->{"frame2"} -> Label(-text => "Maske (\% = Nummer) :") -> grid(-row=>3, -column=>1);
    $self->{"ifmask_entry"} = $self->{"frame2"} -> Entry(-textvariable => \$self->{"ifmask"}) -> grid(-row=>3, -column=>2, -columnspan=>3, -sticky => "nsew");


    $self->{"frame3"} = $self->{"main"} -> Frame() -> pack();
    $self->{"iftype_label"} = $self->{"frame3"} -> Label(-text => "Typ:") -> grid(-row=>1, -column=>1);
    $self->{"iftype_rb1"} = $self->{"frame3"} -> Radiobutton(-variable => \$self->{"animtype"}, -text => "Loop", -value => "Loop") -> grid(-row=>1, -column=>2);
    $self->{"iftype_rb2"} = $self->{"frame3"} -> Radiobutton(-variable => \$self->{"animtype"}, -text => "Pendel", -value => "Pendel") -> grid(-row=>1, -column=>3);


    # Spacer
    $self->{"main"} -> Label(-text => " ") -> pack();
    $self->{"main"} -> Label(-text => "Objekte") -> pack();
    $self->{"frame4"} = $self->{"main"} -> Frame() -> pack();
    $self->{"objcount_label"} = $self->{"frame4"} -> Label(-text => "Anzahl:") -> grid(-row=>1, -column=>1);
    $self->{"objcount_entry"} = $self->{"frame4"} -> Entry(-textvariable => \$self->{"objcount"}) -> grid(-row=>1, -column=>2, -sticky => "nsew");
    $self->{"objblocking_cb"} = $self->{"frame4"} -> Checkbutton(-variable => \$self->{"objblocking"}, -text => "Blocking") -> grid(-row=>2, -column=>1);
    $self->{"objvisible_cb"} = $self->{"frame4"} -> Checkbutton(-variable => \$self->{"objvisible"}, -text => "Visible") -> grid(-row=>2, -column=>2);
    $self->{"objontop_cb"} = $self->{"frame4"} -> Checkbutton(-variable => \$self->{"objontop"}, -text => "On Top") -> grid(-row=>3, -column=>1);
    $self->{"objkilling_cb"} = $self->{"frame4"} -> Checkbutton(-variable => \$self->{"objkilling"}, -text => "Killing") -> grid(-row=>3, -column=>2);

    # Spacer
    $self->{"main"} -> Label(-text => " ") -> pack();
    $self->{"main"} -> Label(-text => "Script") -> pack();
    $self->{"frame5"} = $self->{"main"} -> Frame() -> pack();
    $self->{"ifvar_label"} = $self->{"frame5"} -> Label(-text => "Stammvariable:") -> grid(-row=>4, -column=>1);
    $self->{"ifvar_entry"} = $self->{"frame5"} -> Entry(-textvariable => \$self->{"animvar"}) -> grid(-row=>4, -column=>2, -columnspan=>3, -sticky => "nsew");

    $self->{"ifvar_label"} = $self->{"frame5"} -> Label(-text => "Kommentar:") -> grid(-row=>5, -column=>1);
    $self->{"ifvar_entry"} = $self->{"frame5"} -> Entry(-textvariable => \$self->{"animcomment"}) -> grid(-row=>5, -column=>2, -columnspan=>3, -sticky => "nsew");


    # Spacer
    $self->{"main"} -> Label(-text => " ") -> pack();
    $self->{"frame6"} = $self->{"main"} -> Frame() -> pack();
    $self->{"frame6"} -> Label(-text => "Init-Script") -> grid(-row=>0, -column=>0, -sticky => "nsw");

    $self->{"init_area"} = $self->{"frame6"} -> Frame() -> grid(-row=>1, -column=>0, -sticky => "nswe");
    $self->{"init_entry"} = $self->{"init_area"} -> Text(-width => 40, -height => 5, -wrap => 'none') -> grid(-row=>1,-column=>1);
    $self->{"init_entry_scrolly"} = $self->{"init_area"} -> Scrollbar(-orient=>'v',-command=>[yview => $self->{"init_entry"}])
                                    -> grid(-row=>1,-column=>2,-sticky=>"ns");
    $self->{"init_entry_scrollx"} = $self->{"init_area"} -> Scrollbar(-orient=>'h',-command=>[xview => $self->{"init_entry"}])
                                    -> grid(-row=>2,-column=>1,-sticky=>"ew");
    $self->{"init_entry"} -> configure(-yscrollcommand=>['set', $self->{"init_entry_scrolly"}],
                                      -xscrollcommand=>['set', $self->{"init_entry_scrollx"}]);

    $self->{"init_copy"} = $self->{"frame6"} -> Button(-text => "In die Zwischenablage kopieren",
                                                    -command => [$self => 'copyInit'])
                                            -> grid(-row=>2, -column=>0, -sticky => "ns");



    $self->{"frame6"} -> Label(-text => "  ") -> grid(-row=>0, -column=>1, -rowspan => 3, -sticky => "nsew");
    $self->{"frame6"} -> Label(-text => "Physics-Loop")  -> grid(-row=>0, -column=>2, -sticky => "nsw");
    $self->{"physics_area"} = $self->{"frame6"} -> Frame() -> grid(-row=>1, -column=>2, -sticky => "nswe");
    $self->{"physics_entry"} = $self->{"physics_area"} -> Text(-width => 40, -height => 5, -wrap => 'none') -> grid(-row=>1,-column=>1);

    $self->{"physics_entry_scrolly"} = $self->{"physics_area"} -> Scrollbar(-orient=>'v',-command=>[yview => $self->{"physics_entry"}])
                                    -> grid(-row=>1,-column=>2,-sticky=>"ns");
    $self->{"physics_entry_scrollx"} = $self->{"physics_area"} -> Scrollbar(-orient=>'h',-command=>[xview => $self->{"physics_entry"}])
                                    -> grid(-row=>2,-column=>1,-sticky=>"ew");
    $self->{"physics_entry"} -> configure(-yscrollcommand=>['set', $self->{"physics_entry_scrolly"}],
                                      -xscrollcommand=>['set', $self->{"physics_entry_scrollx"}]);


    $self->{"physics_copy"} = $self->{"frame6"} -> Button(-text => "In die Zwischenablage kopieren",
                                                    -command => [$self => 'copyPhysics'])
                                            -> grid(-row=>2, -column=>2, -sticky => "ns");


    # Spacer
    $self->{"main"} -> Label(-text => " ") -> pack();

    $self->{"start"} = $self->{"main"} -> Button(-text => "Vollgas!",
                                                    -command => [$self => 'genscript_button'])
                                            -> pack();

    MainLoop;

}

sub getTypeList() {
    my $self = shift;

    my @types;

    if($self->{"config"}->{"lastext"} eq ".bmp") {
        @types = (["Windows-Bitmap", '.bmp', 'TEXT'],
                 ["JPEG Image", '.jpg', 'TEXT'],
                 ["PNG", '.png', 'TEXT'],
                 ["All Files", "*"] );
    } elsif($self->{"config"}->{"lastext"} eq ".jpg") {
        @types = (["JPEG Image", '.jpg', 'TEXT'],
                 ["Windows-Bitmap", '.bmp', 'TEXT'],
                 ["PNG", '.png', 'TEXT'],
                 ["All Files", "*"] );
    } elsif($self->{"config"}->{"lastext"} eq ".png") {
        @types = (["PNG", '.png', 'TEXT'],
                 ["Windows-Bitmap", '.bmp', 'TEXT'],
                 ["JPEG Image", '.jpg', 'TEXT'],
                 ["All Files", "*"] );
    } else {
        @types = (["All Files", "*"],
                 ["Windows-Bitmap", '.bmp', 'TEXT'],
                 ["JPEG Image", '.jpg', 'TEXT'],
                 ["PNG", '.png'], 'TEXT');
    }

    return \@types;

}

#This is executed when the button is pressed
sub selectInfile1($) {
    my $self = shift;

    my $fname = $self->{"main"}->getOpenFile(-filetypes => $self->getTypeList(),
                                        -initialfile=> $self->{"ifname1"},
                                        -defaultextension => $self->{"config"}->{"lastext"},
                                        -initialdir => $self->{"config"}->{"lastdir"});

    if($fname) {
        $fname =~ s/^(.*)\///;
        $self->{"config"}->{"lastdir"} = $1;
        $fname =~ /(\..*)$/;
        $self->{"config"}->{"lastext"} = lc $1;
        $self->{"ifname1"} = $fname;
    }
}

sub selectInfile2($) {
    my $self = shift;

    my $fname = $self->{"main"}->getOpenFile(-filetypes => $self->getTypeList(),
                                        -initialfile=> $self->{"ifname2"},
                                        -defaultextension => $self->{"config"}->{"lastext"},
                                        -initialdir => $self->{"config"}->{"lastdir"});

    if($fname) {
        $fname =~ s/^(.*)\///;
        $self->{"config"}->{"lastdir"} = $1;
        $fname =~ /(\..*)$/;
        $self->{"config"}->{"lastext"} = lc $1;
        $self->{"ifname2"} = $fname;
    }
}

#This is executed when the GenArgs is pressed
sub genargs_button($) {
    my $self = shift;

    my ($start, $end) = ("", "");

    # get start and end arguments
    if($self->{"ifname1"} =~ /(\d+)/) {
        $start = $1;
        $self->{"ifstart"} = $start + 0;
    }
    if($self->{"ifname2"} =~ /(\d+)/) {
        $end = $1;
        $self->{"ifend"} = $end + 0;
    }

    # Get Padding
    if(length($start) > 0 && length($start) == length($end)) {
        $self->{"ifpad"} = length($start);
    }

    # Get Mask
    $self->{"ifmask"} = $self->{"ifname1"};
    $self->{"ifmask"} =~ s/\d+/\%/;

}

sub numPad($$) {
    my ($val, $len) = @_;
    while(length($val) < $len) {
        $val = "0$val";
    }
    return $val;
}

#This is executed when the button is pressed
sub genscript_button($) {
    my $self = shift;

#    print $self->{"ifname"}, "\n";

    my $linit = "-- Animation for " . $self->{"animvar"} . "\n" .
                "--    (copy into 'init' function of script)\n" .
                "--    Comment: ". $self->{"animcomment"} . "\n";
    my $lphys = "-- Animation for " . $self->{"animvar"} . "\n" .
                "--    (copy to 'physics' function of script)\n" .
                "--    Comment: ". $self->{"animcomment"} . "\n";

    # Initialize basic struct
    $linit .= $self->{"animvar"} . " = {};\n" .
              $self->{"animvar"} . ".GFX = {};\n" .
              $self->{"animvar"} . ".OBJ = {};\n" .
              $self->{"animvar"} . ".Timer = 0;\n" .
              $self->{"animvar"} . ".Shown = 0;\n" .
              $self->{"animvar"} . ".Max = " . ($self->{"ifend"} - $self->{"ifstart"}) . ";\n" .
              $self->{"animvar"} . ".Delay = " . $self->{"animdelay"} . ";\n" .
              $self->{"animvar"} . ".Count = " . $self->{"objcount"} . ";\n\n";

    # This needs some optimizing for code generation
#    my $cnt = 0;
#   foreach my $i ($self->{"ifstart"} .. $self->{"ifend"}) {
#        my $num = numPad($i, $self->{"ifpad"});
#        my $tmp = $self->{"ifmask"};
#        $tmp =~ s/\%/$num/;
#        $linit .= $self->{"animvar"} . ".GFX[$cnt] = LoadGFX(\"$tmp\");\n";
#        $cnt++;
#    }

    my $cnt = 0;
    $linit .= "gfxcount = 0;\n" .
              "for i = " . $self->{"ifstart"} . ", " . $self->{"ifend"} . ", 1 do\n" .
              "    tmpnum = i;\n";
    if($self->{"ifpad"} > 0) {
        $linit .= "    while(string.len(tmpnum) < " . $self->{"ifpad"} . ") do\n" .
                  "        tmpnum = \"0\" .. tmpnum;\n" .
                  "    end\n";
    }
    my @tmpparts = split/\%/, $self->{"ifmask"};
    $linit .= "    fname = \"$tmpparts[0]\" .. tmpnum .. \"$tmpparts[1]\";\n" .
              "    " . $self->{"animvar"} . ".GFX[gfxcount] = LoadGFX(fname);\n" .
              "    gfxcount = gfxcount + 1;\n" .
              "end\n";


    # Add object(s)
    for(my $i = 0; $i < $self->{"objcount"}; $i++) {
        $linit .= $self->{"animvar"} . ".OBJ[$i] = AddObject(" . $self->{"animvar"} . ".GFX[0], XXX, YYY, " .
                  $self->{"objblocking"} . ", " .
                  $self->{"objvisible"} . ", " .
                  $self->{"objontop"} . ", " .
                  $self->{"objkilling"} . ");\n";
    }


    # Generate physics-loop
    $lphys .= "" . $self->{"animvar"} . ".Timer = " . $self->{"animvar"} . ".Timer + 1;\n" .
	      "if " . $self->{"animvar"} . ".Timer == " . $self->{"animvar"} . ".Delay then\n" .
	      "    " . $self->{"animvar"} . ".Timer = 0;\n" .
	      "    " . $self->{"animvar"} . ".Shown = " . $self->{"animvar"} . ".Shown + 1;\n" .
	      "    if " . $self->{"animvar"} . ".Shown > " . $self->{"animvar"} . ".Max then\n" .
	      "        " . $self->{"animvar"} . ".Shown = 0;\n" .
              "    end\n" .
	      "    for i = 0," . $self->{"animvar"} . ".Count-1,1 do\n" .
	      "        SetGFX(" . $self->{"animvar"} . ".OBJ[i], " . $self->{"animvar"} . ".GFX[" . $self->{"animvar"} . ".Shown]);\n" .
	      "    end\n" .
	      "end\n";

    $self->{"init_entry"} -> Contents($linit);
    $self->{"physics_entry"} -> Contents($lphys);

    # Write config
    foreach my $key (@keys) {
        $self->{"config"}->{$key} = $self->{$key};
    }
    $self->{"config"}->write($self->{"ifname"}, $self->{"ofnametxt"}, $self->{"ofnamebsl"});
#    $self->{"main"} -> messageBox(-message=>"Fertig!",
#		-type=>'ok',-icon=>'info');
#
}

sub copyInit {
    my $self = shift;
    my $txt = $self->{"init_entry"} -> Contents();

    $self->{"init_entry"}->clipboardClear();
    $self->{"init_entry"}->clipboardAppend($txt);
}

sub copyPhysics {
    my $self = shift;
    my $txt = $self->{"physics_entry"} -> Contents();

    $self->{"physics_entry"}->clipboardClear();
    $self->{"physics_entry"}->clipboardAppend($txt);
}


1;
