#!/usr/bin/perl
# porządkuje zdjęcia według nazw

use strict;
use warnings;
use utf8;

use English;

use Getopt::Std;
use File::Copy qw(cp);
use File::Path qw(make_path);
use Capture::Tiny ':all';

use Tk;
use Tk::FileSelect;
use Tk::DialogBox;

our $VERSION = '0.02';

sub help () {
  print "i2dir.pl [-h] -i /input/dir -o /output/dir\n";
  exit 1;
}

sub run ($$@) {
  my ($in, $out, @mnames) = @_;
  my ($in_dir, $out_dir, @flist);

  die $in  . " to nie folder " if not -d $in;
  die $out . " to nie folder " if not -d $out;

  opendir $in_dir,  $in or die "nie mozna otworzyc: $!";
  opendir $out_dir, $out or die "nie mozna otworzyc: $!";

  for (readdir $in_dir) {
    push @flist, $_ if -f $in . "/$_";
  }

  foreach my $f (@flist) {
    if ($f =~ /^.*_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2}).*\.(.*)$/) {
      my ($y, $m, $d, $h, $min, $type) = ($1, $2, $3, $4, $5, $6);
      $m = $mnames[$m - 1];
      if ($m =~ /^\d+$/) {
        $m = sprintf "%02d", $m;
      }

      if (not -d $out . "/$y/$y\_$m") {
        make_path $out . "/$y/$y\_$m";
      }

      my $i = 0;
      while (-f $out . "/$y/$y\_$m/$y$m$d\_$h$min" . ($i > 0 ? "_$i" : "")
        . ".$type") {
        $i++;
      }

      cp $in . "/$f", $out . "/$y/$y\_$m/$y$m$d\_$h$min"
        . ($i > 0 ? "_$i" : "") . ".$type" or die "blad kopiowania: $!";
    } else {
      if (not -d $out . "/inne") {
        make_path $out . "/inne";
      }

      cp $in . "/$f", $out . "/inne/$f" or die "blad kopiowania: $!";
    }
  }

  closedir $in_dir;
  closedir $out_dir;
}

sub graphics () {
  my $mw = MainWindow->new;
  my ($d1_n, $d2_n, $normal_m) = (0, 0, 0);

  $mw->title(":^)");

  $mw->Button(
    -text => 'folder z nieuporządkowanymi plikami',
    -command => sub {
      $d1_n = $mw->chooseDirectory(
        -title => "folder z nieuporządkowanymi plikami",
      );
    }
  )->pack(-anchor => 'w', -padx => '10', -pady => '10');

  $mw->Button(
    -text => 'folder na uporządkowane pliki (preferowalnie pusty)',
    -command => sub {
      $d2_n = $mw->chooseDirectory(
        -title => "folder na uporządkowane pliki",
      );
    }
  )->pack(-anchor => 'w', -padx => '10', -pady => '10');

  my $m_names = $mw->Checkbutton(
    -text => "polskie nazwy miesięcy zamiast numerycznych (styczeń, luty, ...)",
    -variable => \$normal_m
  )->pack(-anchor => 'w', -padx => '10', -pady => '10');

  my $ok_button = $mw->Button(
    -text => "porządkuj!",
    -command => sub {
      my @mnames;
      if ($normal_m != 0) {
        @mnames = ('styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec',
          'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad',
          'grudzień');
      } else {
        @mnames = (1..12);
      }

      eval { run $d1_n, $d2_n, @mnames };
      my $ret = $@;
      $ret = "uporządkowano pomyślnie" if $ret eq '';

      my $dialog = $mw->DialogBox(-title => "proces", -buttons => ["OK"]);
      my $text = $dialog->Text(
        -background => 'white',
        -foreground => 'black',
        -font => "monospace 10",
      )->pack();
      $text->insert("0.0", $ret);
      $text->configure(-state => "disabled");
      $dialog->Show;
    }
  )->pack(-anchor => 'w', -padx => '10', -pady => '10');

  MainLoop;
}

my (%opt, @mnames);

getopts('i:o:hm:g', \%opt);

if ($OSNAME eq 'MSWin32' or defined $opt{'g'}) {
  graphics;
  exit;
}

help if not defined $opt{'i'};
help if not defined $opt{'o'};

if (defined $opt{'m'}) {
  @mnames = eval $opt{'m'} or die $!;
} else {
  @mnames = (1..12);
}

run $opt{'i'}, $opt{'o'}, @mnames;

__END__
=head1 i2dir.pl

i2dir - organizes images based on it's names

=head1 SYNOPSIS

  i2dir.pl [-h] [-g] -i /path/to/unorganized/ -o /output/dir/

=head1 DESCRIPTION

  organizes files like this:
    IMG_20230101_1333.png -> 2023/2023_01/20230101_1333.png
  etc.

  handles files based on this regular expression:
  /^.*_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2}).*\.(.*)$/

=head2 EXPORT

None

=head2 CAVEATS

polish interface

=head1 AUTHOR

krzysckh, E<lt>kpm@linux.plE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2023 by krzysckh

under BSD 2-clause

=cut
