#!/usr/bin/perl

# PODNAME: tanker_upload

=encoding UTF-8
=cut

=head1 SYNOPSIS

tanker_upload --project=project_id

 Obligatory options:

      --project=project_id  # project id in the tanker
      --token=12345         # project secret token
      --langs=ru,en         # comma separated list of langs that will be
                            # used in upload process

 Optional options:

      --branch=feature_x        # branch name. Default is master
      --help                    # show this message and exit
      --use_test_tanker         # work with tanker-test.yandex-team.ru
      --dont_write_original     # the field original language in tanker will
                                # not be filled

Script will do several uploads to the tanker. The number of uploads is the
same as number of languages that are passed to the script.

For the each upload script will do the following. Script will find all .po
files in the folder ./locale/keysets/LANG/. Script will fix po files to make
msgids unique over all files. Script will upload fixed po files as the keysets
to the tanker. If there is no keyset in the tanker it will be created or it
will be merged.

In case of merge the script do the following:

 * msgid is in the file and is in the tanker - after the merge the msgid in
   tanker will stay the same. It it was translated in tanker the translation
   will not be changed (But the translation will be marked as 'Expired').
 * msgid is in the file and is not in the tanker - msgid will be created in
   tanker and the field "original language" will also get the msgid string.
 * msgid is not in the file and is in the tanker - msgid will be deleted in
   tanker, no matter if it is translated or not.

    locale/
    └── keysets
        ├── keyset_name1.po
        └── keyset_name2.po

=cut

# common modules
use strict;
use warnings FATAL => 'all';
use 5.008;
use Carp;
use Getopt::Long;
use File::Slurp;
use Term::ANSIColor qw(:constants);
use Pod::Usage;

use Yandex::Tanker;

# subs
sub get_correct_opts {

    my $help;
    my $project;
    my $token;
    my $use_test_tanker;
    my $dont_write_original;
    my $branch;
    my $langs;

    GetOptions(
        'help' => \$help,
        'project=s' => \$project,
        'token=s' => \$token,
        'branch=s' => \$branch,
        'use_test_tanker' => \$use_test_tanker,
        'dont_write_original' => \$dont_write_original,
        'langs=s' => \$langs,
    );

    if ($help) {
        pod2usage({-message => ''});
        exit;
    }

    # --project
    if (not defined $project) {
        Yandex::Tanker::_print_error_and_exit("'--project' is missing");
    }

    # --langs
    if (not defined $langs) {
        Yandex::Tanker::_print_error_and_exit("'--langs' is missing");
    }

    my @langs = split(/,/, $langs);

    if (not @langs) {
        Yandex::Tanker::_print_error_and_exit("'--langs' is missing");
    }

    my $opts = {
        project => $project,
        token => $token,
        use_test_tanker => $use_test_tanker,
        dont_write_original => $dont_write_original,
        branch => $branch,
        langs => \@langs,
    };

    return $opts;
}

sub get_po_files {
    my ($lang) = @_;

    my $dir = "./locale/keysets/$lang";

    if (!-d $dir) {
        croak "Dir '$dir' does not exist";
    }

    my @files = glob("$dir/*.po");

    if (!@files) {
        croak "No po files found in dir '$dir'";
    }

    return @files;
}

sub get_fixed_po_files {
    my (%opts) = @_;

    my @fixed_po_files;

    my $dir = './locale/fixed_keysets/';
    unless (-d $dir) {
        mkdir($dir) or croak "Can't create dir '$dir': $!";
    }

    $dir .= $opts{lang};
    if (-d $dir) {
        croak "Error. Tmp dir for fixed keysets '$dir' already exist.";
    } else {
        mkdir($dir) or croak "Can't create dir '$dir': $!";
    }

    my %seen_msgids;
    my %seen_msgids_with_context;

    my $tanker = $opts{tanker};

    foreach my $file (@{$opts{po_files}}) {
        $file =~ m{([^/]*)$};
        my $filename = $1;
        my $po_content = read_file($file);
        my $fixed_po_content = '';

        foreach my $block ($tanker->_split_po_to_blocks($po_content)) {

            if ($tanker->_is_first_block($block)) {
                $fixed_po_content .= $block . "\n";
            } else {

                my $msgid = $tanker->_get_msgid_from_block($block);
                my $msgctxt = $tanker->_get_msgctxt_from_block($block);

                if (defined $msgctxt) {

                    if (not defined $seen_msgids_with_context{$msgctxt}->{$msgid}) {
                        $fixed_po_content .= $block . "\n";
                    }

                    $seen_msgids_with_context{$msgctxt}->{$msgid}++;

                } else {

                    if (not defined $seen_msgids{$msgid}) {
                        $fixed_po_content .= $block . "\n";
                    }

                    $seen_msgids{$msgid}++;
                }

            }
        }

        write_file("$dir/$filename", $fixed_po_content);
        push @fixed_po_files, "$dir/$filename";

    }

    return @fixed_po_files;
}

sub get_keyset_name_from_file {
    my ($file) = @_;

    $file =~ m{^.*/(.*)\.po$};
    my $name = $1;

    return $name;
}

sub delete_fixed_po_files {
    my $lang = shift || '';
    my $dir = './locale/fixed_keysets/' . $lang;

    system("rm -rf $dir") and croak "Can't rm dir '$dir': $!";
}

sub delete_keysets_in_tanker_but_not_local {
    my (%opts) = @_;

    my @keysets_in_tanker_but_not_local
        = grep {not Yandex::Tanker::_is_in_array($_, $opts{local_keysets})} @{$opts{keysets_in_tanker}};

    foreach my $keyset (@keysets_in_tanker_but_not_local) {
        $opts{tanker}->delete_keyset(
            keyset => $keyset,
            branch => $opts{branch},
        );
    }

    return '';
}

# main
sub main {
    my $opts = get_correct_opts();

    my $tanker_url;
    if ($opts->{use_test_tanker}) {
        $tanker_url = $Yandex::Tanker::TEST_URL;
    } else {
        $tanker_url = $Yandex::Tanker::PROD_URL;
    }

    my $tanker = Yandex::Tanker->new({
        url     => $tanker_url,
        project => $opts->{project},
        token   => $opts->{token},
    });

    my %local_keysets = ();
    my @keysets_in_tanker = ();

    foreach my $lang (@{$opts->{langs}}) {
        my @po_files = get_po_files($lang);
        @keysets_in_tanker = $tanker->get_keysets(
            branch => $opts->{branch},
        );
        my @fixed_po_files = get_fixed_po_files(
            tanker => $tanker,
            po_files => \@po_files,
            lang => $lang
        );

        foreach my $file (@fixed_po_files) {
            my $keyset = get_keyset_name_from_file($file);
            $local_keysets{$keyset} = 1 unless $local_keysets{$keyset};

            my %opts = (
                file        => $file,
                'keyset'    => $keyset,
                'language'  => $lang,
                format      => 'po',
                branch      => $opts->{branch},
            );

            if ($opts->{dont_write_original}) {
                $opts{'original-not-id'} = 1;
            }

            if (Yandex::Tanker::_is_in_array($keyset, \@keysets_in_tanker)) {
                $tanker->replace_keyset(%opts);
            } else {
                $tanker->create_keyset(%opts);
            }
        }

        delete_fixed_po_files($lang);
    }

    delete_fixed_po_files();

    delete_keysets_in_tanker_but_not_local(
        tanker => $tanker,
        local_keysets => [keys(%local_keysets)],
        keysets_in_tanker => \@keysets_in_tanker,
        branch => $opts->{branch},
    );
}

main();
__END__
