package Common::Deploy::Info;

use lib '/app/tools/common/lib';
use Common::RSApp;
use Common::Deploy;
use Common::Date;

use File::Basename;
use Data::Dumper;
use Storable qw( retrieve store );

use Common::Config;

use base 'Common::XMLObject';

sub _dataFile { 'sysadmin/conf/release.info' }

sub _init {
    my $self = shift;

    return $self;
}

sub _retrieve {
    my $self = shift;
    $self->_updateInfo();
    return retrieve( $self->_dataFilePath() ) || die "Failed to open storage: $!";
}

sub _store {
    my $self = shift;
    my $data = shift || die "nothing to store";

    Common::Log::Debug "Storing info: " . Dumper $data;

    store( $data, $self->_dataFilePath() ) || die "Failed to store: $!";
    $self->_saveInfo();
}

sub _dataFilePath {
    my $self       = shift;
    my $repository = Common::Deploy->repository();
    my $path       = "$repository/trunk/code/" . $self->_dataFile();

    Common::Deploy->checkoutBranch("trunk") unless ( -d "$repository/trunk" );

    return $path;
}

sub _updateInfo {
    my $self = shift;
    my $file = $self->_dataFilePath();
    my $dir  = dirname($file);
    my $file = basename($file);

    my $cmd = "cd $dir && cvs -q up $file 2>&1";

    Common::Log::Debug("Execute: $cmd");

    my $output = `$cmd`;

    die "Failed: \n$output" if ($?);
}

sub _saveInfo {
    my $self = shift;
    my $file = $self->_dataFilePath();
    my $dir  = dirname($file);
    my $file = basename($file);

    my $cmd = "cd $dir && cvs -q ci -m 'automated commit' $file 2>&1";

    Common::Log::Debug("Execute: $cmd");

    my $output = `$cmd`;

    die "Failed: \n$output" if ($?);
}

sub releases {
    my $self = shift;

    my $data = $self->_retrieve();

    return $self->_sortReleases( $data->{releases} );
}

sub branches {
    my $self = shift;
    my $data = $self->_retrieve();

    return $self->_sortBranches( $data->{branches} );
}

sub _sortBranches {
    my $self = shift;
    my $data = shift || return;
    my @store;
    my @result;

    foreach my $key ( keys %$data ) {
        push( @store, "$data->{$key}\t$key" );
    }

    foreach my $record ( sort @store ) {
        my ( $date, $branch ) = split( /\t/, $record );
        push( @result, { name => $branch, created => $date } );
    }

    return @result;
}

sub _sortReleases {
    my $self = shift;
    my $data = shift || return;
    my @store;
    my @result;

    foreach my $key ( keys %$data ) {
        push( @store, "$data->{$key}->{created}\t$key" );
    }

    foreach my $record ( sort @store ) {
        my ( $date, $branch ) = split( /\t/, $record );
        push( @result, { name => $branch, created => $date, released => $data->{$branch}->{released} } );
    }

    return @result;
}

sub addBranch {
    my $self = shift;
    my $branch = shift || die "branch name required";

    my $data = $self->_retrieve();

    die("Branch already exists with requested name: '$branch'\n")
      if ( $data->{branches}->{$branch} );

    $data->{branches}->{$branch} = Common::Date->today();

    $self->_store($data);
}

sub addRelease {
    my $self = shift;
    my $name = shift || die "branch name required";

    my $data = $self->_retrieve();

    die("Release already exists with requested name: '$name'\n")
      if ( $data->{releases}->{$name} );

    $data->{releases}->{$name} = { created => Common::Date->today() };

    $self->_store($data);
}

sub markRelease {
    my $self = shift;
    my $name = shift || die "branch name required";

    my $data = $self->_retrieve();

    die("Release does not exists with requested name: '$name'\n")
      unless ( $data->{releases}->{$name} );

    $data->{releases}->{$name} = { released => Common::Date->today() };

    $self->_store($data);
}

sub validName {
    my $self = shift;
    my $name = shift || die;
    my $data = $self->_retrieve();

    return defined( $data->{releases}->{$name} ) || defined( $data->{branches}->{$name} ) ? 1 : undef;
}

sub branchExist {
    my $self = shift;
    my $name = shift || die;
    my $data = $self->_retrieve();

    return defined( $data->{branches}->{$name} ) ? 1 : undef;
}

sub releaseExist {
    my $self = shift;
    my $name = shift || die;
    my $data = $self->_retrieve();

    return defined( $data->{releases}->{$name} ) ? 1 : undef;
}

1;
