#!/usr/bin/env perl

use strict;
use warnings;
use utf8;

use Encode;
use FindBin qw($Bin);
use Fcntl;
use Glib qw{ TRUE FALSE };
use Gtk2 '-init';
use Config::General;
use Net::FTP;
use Image::ExifTool qw(:Public);
use Data::Dumper;
use File::Basename;
use File::Spec::Functions;

use constant { cstrVersion => '0.0.1' };

my %defprefs = (
    stockscolnum => 3,
    padding      => 2,
    windowwidth  => 800,
    windowheight => 800,
    passive_ftp  => 1,
    debug        => 1,
    stdout       => 1,
    vpnMain      => { position => 0 },
    expLog       => { expanded => FALSE },
    Stocks       => {
        'fotolia.com' => {
            server    => 'ftp.fotolia.com',
            defactive => 1,
            user      => '',
            password  => ''
        },
        'dreamstime.com' => {
            server    => 'upload.dreamstime.com',
            defactive => 1,
            user      => '',
            password  => ''
        },
        '123rf.com' => {
            server    => 'ftp.123rf.com',
            defactive => 1,
            user      => '',
            password  => ''
        },
        'shutterstock' => {
            server    => 'ftp.shutterstock.com',
            defactive => 1,
            user      => '',
            password  => ''
        },
        'bigstockphoto' => {
            server    => 'ftp.bigstockphoto.com',
            defactive => 1,
            user      => '',
            password  => ''
        },
        'crestock' => {
            server    => 'ftp.crestock.com',
            defactive => 1,
            user      => '',
            password  => ''
        },
        'lori' => {
            server    => 'ftp.lori.ru',
            defactive => 1,
            user      => '',
            password  => ''
        }
    }
);

my $builder;
my $wndMain;
my %prefs;
my %databin;

my $conffilename = '.photostock-helper';
my $conffile     = catfile($ENV{HOME}, $conffilename);

sub interc {
    my $msg = shift;
    my $lvl = shift || 1;

    if ( $lvl >= $prefs{debug} or $lvl == 0 ) {
        if ( $prefs{stdout} ) {
            print "$msg";
        }
        my $txvLog = $builder->get_object('txvLog');
        my $txbLog = $txvLog->get_buffer;
        $txbLog->insert_at_cursor("$msg");
        my $mark = $txbLog->create_mark( undef, $txbLog->get_end_iter, FALSE );
        $txvLog->scroll_to_mark( $mark, 0, 0, 0, 1 );
    }
}

sub intercn {
    my $msg = shift;
    my $lvl = shift || 1;

    interc( "$msg\n", $lvl );
}

sub kill_duplicates {
    my @list = @_;
    my %uniq;
    my $result = [];
    my $dups   = [];

    foreach my $val (@list) {
        if ( exists $uniq{$val} ) {
            if ( !exists $uniq{ $val . '#dup' } ) {

                push @$dups, $val;
                $uniq{ $val . '#dup' } = 1;
            }

        }
        else {
            push @$result, $val;
            $uniq{$val} = 1;
        }
    }

    return $result, $dups;
}

sub set_image_changed{
	my $status=shift;
	my $details=shift;
	#intercn('set_image_changed[' . $details . ']: ' . $status);
	$databin{image_changed}=$status;
}

sub get_image_changed{
	return $databin{image_changed};
}

sub init_prefs {

    if ( !-e $conffile ) {
        sysopen( my $FH, $conffile, O_WRONLY | O_EXCL | O_CREAT )
          or die "can't open$conffile: $!";
    }
    my $conf = new Config::General(
        -ConfigPath            => [ $ENV{HOME} ],
        -UTF8                  => 1,
        -ConfigFile            => $conffilename,
        -DefaultConfig         => \%defprefs,
        -MergeDuplicateOptions => 1,
        -MergeDuplicateBlocks  => 1,
        -SaveSorted            => 1
    );
    %prefs = $conf->getall;
}

sub init_stocks_activity {

    # -- Initialization stocks activity

    while ( my ( $stockname, $stockparams ) = each( %{ $prefs{'Stocks'} } ) ) {
        $stockparams->{active} = $stockparams->{defactive};
        #if ( $prefs{'debug'} == 2 ) {

            #print "$stockname:\n";
            #my $msg = shift;
            #my $lvl = shift || 1;

            #if ( $lvl >= $prefs{debug} or $lvl == 0 ) {
            #    if ( $prefs{stdout} ) {
            #        print "$msg";
            #    }
            #    my $txbLog = $builder->get_object('txvLog')->get_buffer;
            #    $txbLog->insert_at_cursor("$msg");
            #}

            #            while ( my ( $paramname, $paramval ) =
            #               each( %{ $prefs{'Stocks'}->{$stockname} } ) )
            #          {

            #                print "\t$paramname=$paramval\n";
            #         }
        #}

    }
}

sub init_stocks {

    # -- Define and assemble Stocks area

    my $tblStocks = $builder->get_object('tblStocks');
    $tblStocks->resize( 1, $prefs{'stockscolnum'} );
    my $test = $tblStocks->get('n-rows');

    my $cr = 0;
    my $cc = -1;
    my $i  = 0;

    foreach my $stockname ( sort keys %{ $prefs{'Stocks'} } ) {

        my $stockparams = $prefs{'Stocks'}->{$stockname};
        $i += 1;
        my $modulo = $i % $prefs{'stockscolnum'};

        if ( $modulo == 1 ) {
            $tblStocks->resize( ++$cr, $prefs{'stockscolnum'} );
            $cc = 0;
        }
        else {
            $cc += 1;
        }
        my $checkbox = Gtk2::CheckButton->new($stockname);

        if ( $stockparams->{defactive} ) { $checkbox->set_active(1) }

        $checkbox->signal_connect(
            clicked => sub {
                $prefs{'Stocks'}->{$stockname}->{active} =
                  $checkbox->get_active;

                #print "toggled: " . $prefs{'Stocks'}->{$stockname}->{active};
            }
        );

        $tblStocks->attach_defaults( $checkbox, $cc, $cc + 1, $cr, $cr + 1 );
    }
}

sub init_layout {

    $wndMain->signal_connect( configure_event => \&on_wndMain_configure_event );
    $wndMain->set_default_size( $prefs{windowwidth}, $prefs{windowheight} );

    $builder->get_object('ntbMain')->set_current_page( $prefs{lasttab} || 0 );

    my $vpnMain = $builder->get_object('vpnMain');
    $vpnMain->set_position(
             $prefs{vpnMain}->{position}
          or $vpnMain->allocation->height
    );

    $builder->get_object('expLog')->set_expanded( $prefs{expLog}->{expanded} );

    #May be it is will be possible to change selection mode in Glade in future
    my $tvwImages = $builder->get_object('tvwImages');
    $tvwImages->set_has_tooltip(TRUE);
    $builder->get_object('tvwImages')->get_selection->set_mode('multiple');

    #

    my $fch    = $builder->get_object('fchRegister');
    my $filter = Gtk2::FileFilter->new;
    $filter->set_name('JPEG');
    $filter->add_mime_type('image/jpeg');
    $fch->add_filter($filter);
    $fch->set_current_folder( $prefs{lastfolder} or $ENV{HOME} );
    $builder->get_object('chbAutoSet')->set_active( $prefs{autoset} );
    $builder->get_object('chbKillDuplicates')
      ->set_active( $prefs{killdup_keywords} );
    $builder->get_object('chbDefaultCopyright')
      ->set_active( $prefs{default_copyright} );
    $builder->get_object('tmsCopyright')->set_sort_column_id( 0, 'descending' );

    #load copyrights
    my $cbx   = $builder->get_object('cbxCopyright');
	#Forced set_text_column call for strange Gtk2::Builder behaviour
	#it is not initializes text column for TreeModelSort o_O
	#and raise Gtk-CRITICAL **: gtk_tree_model_get_n_columns: assertion `GTK_IS_TREE_MODEL (tree_model)' failed
	$cbx->set_text_column(1);
    my $model = $cbx->get_model->get_model;
    while ( my ( $copyright, $time ) = each( %{ $prefs{'copyrights'} } ) ) {
        $copyright =~ s/%20/ /;
		
        my $iter = $model->append;
        $model->set( $iter, 0 => $time, 1 => $copyright );
    }

}

sub init {
    init_prefs;
    init_stocks_activity;
    init_stocks;
    init_layout;
    $wndMain->set_title( 'PhotoStock Helper v' . cstrVersion );
}

sub register_new_image {
    my $filepath = shift;
	#print "$filepath\n";
    my ( $FileName, $DirectoryName ) = fileparse($filepath);
    if ( $FileName ) {

        #print "$DirectoryName, $FileName\n";

        my $tvwImages  = $builder->get_object('tvwImages');
        my $tree_store = $tvwImages->get_model;

        my $iter = $tree_store->append;

        $tree_store->set( $iter, 0 => $DirectoryName, 1 => $FileName );
    }

}

sub register_new_images {
    my $filechoose = $builder->get_object('fchRegister');

    my $tvwImages = $builder->get_object('tvwImages');
    my $model     = $tvwImages->get_model;
    my %exists;
    $model->foreach(
        sub {
            my $model = shift;
            my $path  = shift;
            my $iter  = shift;
            my ( $filepath, $file ) = $model->get( $iter, 0, 1 );

            undef( $exists{ $filepath.$file  } );

            return FALSE;
        }
    );

    foreach my $filename ( $filechoose->get_filenames ) {
	
        if ( not exists( $exists{$filename} ) ) {

            register_new_image($filename);
        }
    }
}

sub fin_prefs {

    #store copyrights
    my $cbx   = $builder->get_object('cbxCopyright');
    my $model = $cbx->get_model;
    undef( $prefs{copyrights} );
    $model->foreach(
        sub {
            my $model = shift;
            my $path  = shift;
            my $iter  = shift;
            my ( $time, $copyright ) = $model->get( $iter, 0, 1 );
            $copyright =~ s/ /%20/;

            #intercn($copyright);
            $prefs{copyrights}->{$copyright} = $time;

            return FALSE;
        }
    );

    my $conf = new Config::General(
        -ConfigHash => \%prefs,
        -UTF8       => 1,
        -SaveSorted => 1
    );

    $conf->save_file($conffile);
}

sub fin_layout {
    $prefs{lasttab} = $builder->get_object('ntbMain')->get_current_page;
    $prefs{lastfolder} =
      $builder->get_object('fchRegister')->get_current_folder;
    $prefs{vpnMain}->{position} = $builder->get_object('vpnMain')->get_position;
    $prefs{expLog}->{expanded}  = $builder->get_object('expLog')->get_expanded;
    $prefs{autoset} = $builder->get_object('chbAutoSet')->get_active;
    $prefs{default_copyright} =
      $builder->get_object('chbDefaultCopyright')->get_active;
    $prefs{killdup_keywords} =
      $builder->get_object('chbKillDuplicates')->get_active;
}

sub fin {
    fin_layout;

    fin_prefs;
    Gtk2->main_quit();
}

sub ftp_it {

    my ( $stockname, @filenames ) = @_;
    my $txbLog = $builder->get_object('txvLog')->get_buffer;

    my $stock = $prefs{Stocks}->{$stockname};

    intercn( 'Uploading to ' . $stockname . '...' );

    my $ftpobj;

    Gtk2->main_iteration while Gtk2->events_pending;

    if ( $ftpobj =
        Net::FTP->new( $stock->{server}, Passive => $prefs{passive_ftp} ) )
    {
        intercn $stock->{server} . ' connect: ' . $ftpobj->message, 1;

        #print "connected\n";

        if ( $ftpobj->login( $stock->{user}, $stock->{password} ) ) {
            intercn $stock->{server} . ' login: ' . $ftpobj->message, 1;

            #print "logged in\n";
            if ( $ftpobj->cwd( scalar( $stock->{dir} ) || '/' ) ) {
                intercn $stock->{server} . ' cwd: ' . $ftpobj->message, 1;

                #print "cwd\n";

                $ftpobj->binary;
                intercn $stock->{server} . ' binary: ' . $ftpobj->message, 1;

                foreach my $filename (@filenames) {

                    Gtk2->main_iteration while Gtk2->events_pending;

                    interc( "\tFile: " . $filename . '... ' );

                    if ( $ftpobj->put($filename) ) {

                        #print "put\n";
                        intercn('Succeed.');
                    }
                    else {
                        intercn('Failed!');

                        #print "put error\n";
                    }
                    print $!;
                    print "$stock->{server} put: " . $ftpobj->message;
                }
            }
            else { intercn('Change directory error!') }

            $ftpobj->quit;
            intercn $stock->{server} . ' quit: ' . $ftpobj->message, 1;
        }
        else { intercn('Log in error!'); }
    }
    else { intercn('Connect error!'); }
}

sub upload {

    my $txbLog    = $builder->get_object('txvLog')->get_buffer;
    my $lsmImages = $builder->get_object('lsmImages');
    my @filenames;

    #$txbLog->set_text("");

    $lsmImages->foreach(
        sub {
            my $model = shift;
            my $path  = shift;
            my $iter  = shift;

            push( @filenames, catfile( $model->get_value( $iter, 0, 1 ) ) );

            return FALSE;
        }
    );

    while ( my ( $stockname, $stockparams ) = each( %{ $prefs{Stocks} } ) ) {
        #print "$stockname: $stockparams->{active}\n" if $prefs{debug};
        if ( $stockparams->{active} ) {

            intercn 'Upload', 0;
            ftp_it( $stockname, @filenames );
        }

    }
}

sub update_image {
    my $image = $builder->get_object('imgImage');
    my $pixbuf =
      Gtk2::Gdk::Pixbuf->new_from_file( $databin{selected_image_filepath} );

    my $img_width  = $pixbuf->get_width;
    my $img_height = $pixbuf->get_height;

    my $hpn         = $builder->get_object('vpnProperties');
    my $rect        = $hpn->allocation;
    my $dest_width  = $rect->width;
    my $dest_height = $rect->height - $hpn->get_position;

    my $xscaleq = $dest_width / $img_width;
    my $yscaleq = $dest_height / $img_height;
    my $scaleq  = $xscaleq <= $yscaleq ? $xscaleq : $yscaleq;

    #    print join( '; ',
    #        $img_width, $img_height, $dest_width, $dest_height,
    #        $xscaleq,   $yscaleq,    $scaleq )
    #      . "\n";

    $image->set_from_pixbuf(
        $pixbuf->scale_simple(
            $img_width * $scaleq,
            $img_height * $scaleq, 'bilinear'
        )
    );

}

sub get_default_copyright {
    my $cbx    = $builder->get_object('cbxCopyright');
    my $model  = $cbx->get_model;
    my $result = $model->get( $model->get_iter_first, 1 );
    return $result;
}

sub keywords_list {
    my $txbKeywords = $builder->get_object('txvKeywords')->get_buffer;
    return split(
        /,+\s*|\v/m,
        $txbKeywords->get_text(
            $txbKeywords->get_iter_at_offset(0),
            $txbKeywords->get_iter_at_offset(-1),
            TRUE
        )
    );
}

sub update_keywords_count{
	my $keywords_count = scalar keywords_list;
	my $lblKewordsCount = $builder->get_object('lblKeywordsCount');
	
	$lblKewordsCount->set_label($keywords_count);
}

sub fill_image_properties {
    my $exifTool = new Image::ExifTool;

    #$exifTool->Options( Binary => 1 );

    my $success = $exifTool->ExtractInfo( $databin{selected_image_filepath} );
    my $info = $exifTool->GetInfo( { Group1 => 'IPTC' } );

    my $isutf8 =
      ( ( $exifTool->GetValue('CodedCharacterSet') || '' ) eq 'UTF8' );

    #intercn($isutf8);

    #my $info    = $exifTool->GetInfo;
    #my @tags    = $exifTool->GetFoundTags;
    #my @groups  = $exifTool->GetGroups;
    #print '@groups:', Dumper(@groups);
    #print '@tags:',   Dumper(@tags);
    #intercn( '$info:' . Dumper($info));

    my $objectname    = ( $exifTool->GetValue('ObjectName')         or '' );
    my $headline    = ( $exifTool->GetValue('Headline')         or '' );
    my $description = ( $exifTool->GetValue('Caption-Abstract') or '' );
    my $keywords    = ( $exifTool->GetValue('Keywords')         or '' );
    my $copyright   = ( $exifTool->GetValue('CopyrightNotice')  or '' );
	
    my $lbl = $builder->get_object('lblUTF8');
	my $Pango_attrlist = $lbl->get_attributes;
	
    if ($isutf8) {
        $objectname    = decode( 'utf8', $objectname );
        $headline    = decode( 'utf8', $headline );
        $description = decode( 'utf8', $description );
        $keywords    = decode( 'utf8', $keywords );
        $copyright   = decode( 'utf8', $copyright );
        
		$Pango_attrlist->change(Pango::AttrStrikethrough->new (FALSE));
		$lbl->set_attributes($Pango_attrlist);
        $lbl->modify_fg( 'normal', Gtk2::Gdk::Color->parse('green') );
		
    }
    else {
		$Pango_attrlist->change(Pango::AttrStrikethrough->new (TRUE));
		$lbl->set_attributes($Pango_attrlist);
        $lbl->modify_fg( 'normal', Gtk2::Gdk::Color->parse('red') );
		
    }

    $builder->get_object('entTitle')->set_text($objectname || $headline);

    $builder->get_object('txvDescription')->get_buffer->set_text(
        $description

    );

    $builder->get_object('txvKeywords')->get_buffer->set_text($keywords);
    update_keywords_count;
	
	my $chbDefaultCopyright = $builder->get_object('chbDefaultCopyright');
	my $is_auto_copyright = 0;
    if ( $chbDefaultCopyright->get_active ) {
        if ( not $copyright ) {
            $copyright = get_default_copyright;
			$is_auto_copyright = 1;
            #intercn( $chbDefaultCopyright->get_child );
            $chbDefaultCopyright->get_child->modify_fg( 'active',
                Gtk2::Gdk::Color->parse('red') );
            set_image_changed(1, 'default copyright');
        }
        else {
            $chbDefaultCopyright->get_child->modify_fg( 'active',
                Gtk2::Gdk::Color->parse('green') );
        }
    }
	
	$builder->get_object('cbxCopyright')
      ->get_child->set_text( $copyright || '' );
	  
	set_image_changed($is_auto_copyright, 'fill');
}

sub remember_copyright {
    my $copyright = shift;
    my $cbx       = $builder->get_object('cbxCopyright');
    my $model     = $cbx->get_model->get_model;

    #check uniqueness of copyright
    #my @copyrights;
    my $present = FALSE;
    $model->foreach(
        sub {
            my $model = shift;
            my $path  = shift;
            my $iter  = shift;
            my $val   = $model->get_value( $iter, 1 );

            #intercn($val);
            $present = ( $copyright eq $val );
            if ($present) {

                #intercn( 'PRESENT:' . $copyright );
                $model->set( $iter, 0, time );
            }

            return $present;
        }
    );
    if ( !$present ) {
        my $iter = $model->append;

        $model->set( $iter, 0 => time, 1 => $copyright );
    }
}

sub store_image_properties {
    my $exifTool = new Image::ExifTool;
    my $obj;
    my $success;

    $success = $exifTool->ExtractInfo( $databin{selected_image_filepath} );
    if ($success) {
        my $isutf8 = ( $exifTool->GetValue('CodedCharacterSet')||'' eq 'UTF8' );

        #
        my $title = $builder->get_object('entTitle')->get_text;
        my $copyright =
          $builder->get_object('cbxCopyright')->get_child->get_text;
        $obj = $builder->get_object('txvDescription')->get_buffer;
        my $description = $obj->get_text( $obj->get_iter_at_offset(0),
            $obj->get_iter_at_offset(-1), TRUE );
        $obj = $builder->get_object('txvKeywords')->get_buffer;
        my $keywords = [keywords_list];
        my $dups;

        if ( $builder->get_object('chbKillDuplicates')->get_active ) {

            ( $keywords, $dups ) = kill_duplicates(@$keywords);
            if (@$dups) {
                intercn(
                    'Killed duplicate keyword(s): ' . join( ', ', @$dups ) );
            }
        }
        if ($isutf8) {
            $title    = encode( 'utf8', $title );
            $description = encode( 'utf8', $description );
            $copyright   = encode( 'utf8', $copyright );
            map { $_ = encode( 'utf8', $_ ) } @$keywords;

        }

        #intercn "extract: $success\n";

        #        $success =
        #          $exifTool->SetNewValue( 'IPTC:CodedCharacterSet',
        #            encode( 'utf8', 'UTF8' ) );
        #        print " UTF8: $success\n";

        #
        $success = $exifTool->SetNewValue( 'IPTC:ObjectName', $title );
        $success = $exifTool->SetNewValue( 'IPTC:Headline', $title );
        
        #intercn $headline . " headline: $success\n";

        #

        $success = $exifTool->SetNewValue(
            'IPTC:Caption-Abstract', $description

        );
        #intercn $description . " description: $success\n";

        #

        $success = $exifTool->SetNewValue(
            'IPTC:CopyrightNotice', $copyright

        );
        if ( $success and length($copyright) ) {
            remember_copyright($copyright);
        }
        #intercn $copyright . " copyright: $success\n";

        #

        $success = $exifTool->SetNewValue(
            'IPTC:Keywords',
            scalar @$keywords
            ? $keywords
            : undef

        );
        #intercn "keywords: $success\n";
        #intercn '$info:', Dumper( $exifTool->GetInfo( { Group1 => 'IPTC' } ) );
        #intercn 'CountNewValues: ' . $exifTool->CountNewValues() . "\n";

        #
        #print 'cancreate:'
        #  . Image::ExifTool::CanCreate('/home/ash/pshelper_test.xmp');
        $success = $exifTool->WriteInfo( $databin{selected_image_filepath} );

        #print $databin{selected_image_filepath} . '.xmp'
        #  . " writeinfo: $success\n";
        #print 'error' . $exifTool->GetValue('Error') . "\n";
        #print 'warning' . $exifTool->GetValue('Warning') . "\n";
    }
    return $success;
}

sub delete_copyright {
    my $cbx       = $builder->get_object('cbxCopyright');
    my $model     = $cbx->get_model->get_model;
    my $copyright = $cbx->get_child->get_text;

    #check uniqueness of copyright
    #my @copyrights;
    my $present = FALSE;
    $model->foreach(
        sub {
            my $model   = shift;
            my $path    = shift;
            my $iter    = shift;
            my $val     = $model->get_value( $iter, 1 );
            my $founded = ( $val eq $copyright );

            if ($founded) {
                $model->remove($iter);
                $cbx->get_child->set_text('');
            }

            return $founded;
        }
    );
}

# -- Signal handlers
sub on_chbDefaultCopyright_toggled {
    my $self                = shift;
    my $data                = shift;
    my $chbDefaultCopyright = $builder->get_object('chbDefaultCopyright');
    if ( not $chbDefaultCopyright->get_active ) {
        $builder->get_object('chbDefaultCopyright')
          ->set_style( $databin{chbDefaultCopyright_style} );

    }
}

sub on_chbDefaultCopyright_map_event {
    my $self = shift;
    my $data = shift;
    $databin{chbDefaultCopyright_style} =
      $builder->get_object('chbDefaultCopyright')->get_style;
    return FALSE;
}

sub on_btnDeleteCopyright_clicked {
    delete_copyright;
}

sub on_cbxCopyright_changed {
    set_image_changed(1, 'copyright');
    return TRUE;
}

sub on_entTitle_changed {
    set_image_changed(1, 'title');
    return TRUE;
}

sub on_txbDescription_changed {
    set_image_changed(1, 'description');
    return TRUE;
}

sub on_txbKeywords_changed {
    set_image_changed(1, 'keywords');
    update_keywords_count;
    return TRUE;
}

sub on_btnSet_clicked {
    my $self = shift;
    my $data = shift;
    store_image_properties;
}

sub on_btnReset_clicked {
    my $self = shift;
    my $data = shift;
    fill_image_properties;
}

sub on_tvwImages_query_tooltip {
    my $tvw          = shift;
    my $x            = shift;
    my $y            = shift;
    my $keyboard_tip = shift;
    my $tooltip      = shift;
    my $data         = shift;

    my ( $model, $path, $iter );

    ( $x, $y, $model, $path, $iter ) =
      $tvw->get_tooltip_context( $x, $y, $keyboard_tip );
    if ($path) {

        #print "$x, $y, $model, $path, $iter\n";

        my $col   = $tvw->get_column(0);
        my @cells = $col->get_cells;
        my $cell  = $cells[0];

        $tooltip->set_text( $model->get_value( $iter, 0 ) );

        $tvw->set_tooltip_cell( $tooltip, $path, $col, $cell );
        return TRUE;
    }
    return FALSE;
}

sub on_tvwImages_cursor_changed {

    #print "on_tvwImages_cursor_changed\n";
    my $tvw  = shift;
    my $data = shift;

    my $model     = $tvw->get_model;
    my $selection = $tvw->get_selection;
    my @row_paths = $selection->get_selected_rows;

    #foreach my $row_path (@row_paths) {
    #    print $model->get_value( $model->get_iter($row_path), 0 ) . "\n";
    #}
	#print "image_changed: " . $databin{image_changed} . "\n";
    if (    get_image_changed
        and $builder->get_object('chbAutoSet')->get_active )
    {
        interc('Autosaving IPTC['.$databin{selected_image_filepath}.']... ');
        if (store_image_properties) {
            intercn('Ok.');
        }
        else {
            intercn('Error!');
        }
    }
    $databin{selected_image_filepath} =
      catfile($model->get_value( $model->get_iter( $row_paths[0] ), 0, 1 ) );

    update_image;
	#print "update_image: " . $databin{image_changed} . "\n";
    fill_image_properties;
}

sub on_tvwImages_row_activated {
    intercn "on_tvwImages_row_activated\n";
}

sub on_btnUpload_clicked {
    upload;
}

sub on_wndMain_configure_event {
    my $widget = shift;
    my $event  = shift;
    my $data   = shift;

    #print $event->width . ';' . $event->height . "\n";

    $prefs{windowwidth}  = $event->width;
    $prefs{windowheight} = $event->height;

    return FALSE;
}

sub on_btnClearAllImages_clicked {
    my $tree_store = $builder->get_object('lsmImages');
    $tree_store->clear;
}

sub on_btnImagesDelete_clicked {
    my $tree_view  = $builder->get_object('tvwImages');
    my $tree_store = $builder->get_object('lsmImages');

    my $selection = $tree_view->get_selection;
    my @rowrefs;

    foreach my $path ( $selection->get_selected_rows ) {
        push( @rowrefs, Gtk2::TreeRowReference->new( $tree_store, $path ) );
    }

    foreach my $rowref (@rowrefs) {
        $tree_store->remove( $tree_store->get_iter( $rowref->get_path ) );
    }

}

sub on_wndMain_destroy {
    fin;
}

sub on_btnRegister_clicked {
    register_new_images;
}

sub main {
	
	$builder = Gtk2::Builder->new();
	$builder->add_from_file(catfile($Bin, '../share/photostock-helper/photostock-helper.glade'));
	$builder->connect_signals(undef);
	$wndMain = $builder->get_object('wndMain');
	
    init;

    $wndMain->show_all();

    Gtk2->main();
}

main();

exit(0);
