#KanDeLa.
#Copyright (C) 2011 Alain Barbason
#
#This file is part of KanDeLa.
#
#KanDeLa is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#KanDeLa is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with KanDeLa.  If not, see <http://www.gnu.org/licenses/>.
#
use strict;
use warnings;
package Commun;
our $view_technique=1;    # to view or not the technique draw.
our $view_pique=0;        # to view or not the pique.
use Data::Dumper;
my %group;                # for Line (or Pin) in a pattern
my $id=0;
sub colorSelect {
    my $class=shift;
    my $currentColor=shift;
    my %liste=$class->getListe();
    my $newColor;
    foreach my $liste (values %liste) {
        if ($liste->select) {
            $newColor=$liste->changeColor($currentColor);
        }
    }
    return $newColor;
}
sub changeColor {
    # choose a new color for pin
    my $self=shift;
    my $currentColor=shift;
    my $couleur=$self->{COULEUR};
    if ($couleur ne $currentColor) {    # apply the color of precedent change
                                        # fixme-m may be initialized value
        $couleur=$currentColor;
    }
    else {                              # torewrite choose color in list
                                        # fixme-m may be initialized value
        if    ($couleur eq "green")  {$couleur="red";}
        elsif ($couleur eq "red")    {$couleur="brown";}
        elsif ($couleur eq "brown")  {$couleur="orange";}
        elsif ($couleur eq "orange") {$couleur="blue";}
        elsif ($couleur eq "blue")   {$couleur="purple";}
        elsif ($couleur eq "purple") {$couleur="white";}
        else                         {$couleur="green";}
    }
    $self->color($couleur);
    return $self->{COULEUR};
}
sub selectInLozenge {
    my $class=shift;
    my %liste=$class->getListe();
    foreach my $liste (values %liste) {
        if ($liste->inLozenge(@_)) {
            $liste->selectionne;
        }
    }
}
sub selectAll {
    my $class=shift;
    my %liste=$class->getListe();
    foreach my $liste (values %liste) {
        $liste->selectionne();
    }
}
sub deselectAll {
    my $class=shift;
    my %liste=$class->getListe();
    foreach my $liste (values %liste) {
        $liste->deselectionne();
    }
}
sub saveAll {
    my $class=shift;
    my $FILE=shift;
    my %liste=$class->getListe();
    foreach my $liste (values %liste) {
        print $FILE $liste->print();
    }
}
sub deleteSelect {
    my $class=shift;
    my %liste=$class->getListe();
    foreach my $liste (values %liste) {
        if ($liste->select) {
            $liste->supprime();
        }
    }
}
sub copySelectTranslate {
    my $class=shift;
    my %liste=$class->getListe();
    foreach my $liste (values %liste) {
        if ($liste->select) {
            $liste->copyTranslate(@_);
        }
    }
}
sub inLozenge {    # rewrite not really a Lozenge, may-be use quadrilateral
    my $class=shift;
    my $x=shift;
    my $y=shift;
    my $x0=shift;
    my $y0=shift;
    my $x1=shift;
    my $y1=shift;
    my $x2=shift;
    my $y2=shift;
    my $x3=shift;
    my $y3=shift;
    return
         ((($y-$y0)-($y1-$y0)/($x1-$x0)*($x-$x0)) > 0)
      && ((($y-$y1)-($y2-$y1)/($x2-$x1)*($x-$x1)) < 0)
      && ((($y-$y2)-($y3-$y2)/($x3-$x2)*($x-$x2)) < 0)
      && ((($y-$y3)-($y0-$y3)/($x0-$x3)*($x-$x3)) > 0);
}
sub myrotation {
    my $angle=shift;
    my $i=shift;
    my $j=shift;
    $angle=$angle/180*3.141592653;
    my $di=$i*cos($angle)+$j*sin($angle);
    my $dj=-$i*sin($angle)+$j*cos($angle);
    return ($di, $dj);
}
sub rot3 {
    my $i=shift;
    my $j=shift;
    my $angle=shift;
    my @coord;
    while (@_ > 0) {
        my ($di, $dj)=myrotation($angle, shift, shift);
        push(@coord, $i+$di, $j+$dj);
    }
    return (@coord);
}
sub createTorsion {
    # dessine une torsion horizontale qui peut etre déplacée (tiret rouge)
    my ($j, $i, $angle, $trans_j, $trans_i)=@_;
    return (
        $::drawing->createLine(
            Commun::rot3(
                $j, $i, $angle,
                Commun::translate($trans_j, $trans_i, -5, 0, +5, 0)
            ),
            -width => 3,
            -fill  => "red",
            -tags  => ["technique"],
        )
    );
}
sub translate {
    # translate un vecteur (tableau de pair)
    my $i=shift;
    my $j=shift;
    my @coord;
    while (@_ > 0) {
        push(@coord, $i+shift, $j+shift);
    }
    return (@coord);
}
sub flip {
    # translate un vecteur (tableau de pair)
    my $flip=shift;
    my @coord;
    while (@_ > 0) {
        if   ($flip==1) {push(@coord, shift, shift);}
        else            {push(@coord, shift, -shift);}
    }
    return (@coord);
}
sub new {
    my $classe=shift;
    my $self={};
    $self->{ID}=$id++;
    $self->{SELECT}=0;
    bless($self, $classe);
    return $self;
}
sub id {
    my $self=shift;
    return $self->{ID};
}
sub reset_id {
    $id=0;
}
sub set_id {
    my $new_id=shift;
    if ($id <= $new_id) {$id=$new_id+1;}
}
sub selectionne {
    my $self=shift;
    $self->{SELECT}=1;
}
sub deselectionne {
    my $self=shift;
    if ($self->{SELECT}==1) {
        $self->{SELECT}=0;
    }
}
# todo use undo by block
my @undo;
my @redo;
my $undo_mode;
my $undo_tempory_mode;
sub undoDesactivated {
    # nothing to do, necessary when load a file, or when use a set of object
    $undo_mode=0;
}
sub undoSave {
    # normal use, save the inverse of any action in @undo
    $undo_mode=1;
}
sub undoRestore {
    # read @undo, restore the action, and save in @redo
    $undo_mode=2;
}
sub undoWalk {
    # possibility to use undo-redo and walking in @undo et @redo
    $undo_mode=3;
}
sub undoSaveMode {
    $undo_tempory_mode=$undo_mode;
}
sub undoRestoreMode {
    $undo_mode=$undo_tempory_mode;
}
sub unDo {
    if (@undo > 0) {
        undoRestore;
        my $undo=pop(@undo);
        chomp($undo);
        my ($action, @undo)=split(/ /, $undo);
        if ($action eq "delete") {
            my ($type, $id)=@undo;
            if ($type eq "Epingle")
            {    # rewrite how use this in one or two lines
                if (exists($Epingle::liste{$id})) {
                    $Epingle::liste{$id}->supprime;
                }
            }
            if ($type eq "Linepique") {
                $Linepique::liste{$id}->supprime;
            }
            if ($type eq "Image") {
                $Image::liste{$id}->supprime;
            }
            if ($type eq "Trait") {
                $Trait::liste{$id}->supprime;
            }
            if ($type eq "Line") {
                $Line::liste{$id}->supprime;
            }
            if ($type eq "Curve") {
                $Curve::liste{$id}->supprime;
            }
        }
        else {
            my ($action, %param)=split(/ /, $undo); # fixme-m rewrite $action==delete with %param
            $param{"-type"}->new(%param);
        }
        undoSave;
    }
}
sub reDo {
    if (@redo > 0) {
        # fixme-m problem if erase obje, and use undo, after redo too often
        undoWalk;
        my $redo=pop(@redo);
        chomp($redo);
        my ($action, %param)=split(/ /, $redo);
        if ($action eq "delete") {
            undef($::liste{$param{"-type"}}); 
        }
        else {
            $param{"-type"}->new(%param);
        }
        undoSave;
    }
}
sub undoPush {
    my $toString=shift;
    if ($undo_mode==1) {
        push(@undo, $toString);
        undef(@redo);
    }
    if ($undo_mode==2) {
        push(@redo, $toString);
    }
    if ($undo_mode==3) {
        push(@undo, $toString);
    }
}
sub undoDelete {
    my $self=shift;
    undoPush("delete " . ref($self) . " " . $self->id . "\n");
}
sub undoCreate {
    my $self=shift;
    undoPush("create " . $self->print);
}
sub undoShow {
    my $classe=shift;
    print "--undo--\n";
    foreach my $obj (@undo) {
        print $obj;
    }
    print "--redo--\n";
    foreach my $obj (@redo) {
        print $obj;
    }
}
sub DESTROY {
    my $self=shift;
    #print "destroy de commun".$self;
}
1;
