package Fedora::VSP;
our $VERSION = 0.001;

use strict;
use warnings;

=encoding utf8

=head1 NAME

Fedora::VSP - Perl version normalization for RPM

=head1 DESCRIPTION

This module provides functions for normalizing Perl version strings for Red Hat Package (RPM) based Linux distributions.

RPM version format and semantics is similar to Perl version strings (vX.Y.Z).
But to exactly. Older Perl's fraction version format (X.YZ) is incompatible
with RPM.

This is an effort to map Perl version strings to RPM version strings.

=head1 FUNCTIONS

=head2 vsp(I<STRING>, I<SHORT>)

Convert a version value into version string format. The output value is
stripped from the leading C<v> symbol.

If conversion fails, C<undef> will be returned.

Empty or undefined string will be normalized to C<undef>.

If I<SHORT> is true, the returned version string will be shortened by cutting
trailing zero groups. If no digit would remain, C<undef> will be returned.
This feature ephases brevity.

=cut

sub vsp {
    my ($input, $short) = @_;

    if (!defined $input) {
        return undef;
    }

    # Remove underscore parts
    $input =~ s/_.*//;

    if (!defined $input || $input eq '') {
        return undef;
    }

    # Dot is a delimiter
    my @parts = split(/\./, $input);
    # XXX: splitting '.' returns (), splitting '.1' returns ('', '1'),
    # handle them specially
    if (@parts == 0) {
        @parts = ('0');
    } elsif ($parts[0] eq '') {
        $parts[0] = '0';
    }

    # Preserve leading part
    my $output = shift @parts;

    # Is this version string or fraction string?
    my $is_vstring = $output =~ s/^v// || @parts != 1;

    # Reformat parts after leading dot
    if (!$is_vstring) {
        # If it's not a vstring and there is only one part after leading
        # dot, it's a fraction number
        my $fraction = $parts[0];
        @parts = ();

        # Augment digits to factor of 3
        my @digits = split('', $fraction);
        my $trailer = ($#digits + 1) % 3;
        if ($trailer) {
            push @digits, '0';
            if ($trailer == 1) {
                push @digits, '0';
            }
        }

        # Split it into triples
        my $i = 0;
        my $triple = '';
        for (@digits) {
            $i++;
            $triple .= $_;
            if ($i == 3) {
                $i = 0;
                push @parts, $triple;
                $triple = '';
            }
        }
    }

    # Append necessary number of parts to get X.Y.Z format
    if (@parts < 2) {
        push @parts, '0';
        if (@parts < 2) {
            push @parts, '0';
        }
    }

    # Concatenate parts
    for my $part (@parts) {
        # Strip leading zeros
        $part =~ s/^0*(?=.)//;
        $output .= '.' . $part;
    }

    # Shorten if requested
    if ($short) {
        # Cut off all trailing zero groups
        $output =~ s/(?:\.0*)*$//;
        # Drop 0 integer
        if ($output =~ /^0+\.?$/) {
            $output = undef;
        }
    }

    return $output;
}

=head1 AUTHOR

Petr Písař <ppisar@redhat.com>

=head1 COPYING

Copyright (C) 2015  Petr Písař <ppisar@redhat.com>

This program 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.

This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.

=cut

