#!/usr/bin/perl

use strict;
use warnings;

use Test::More tests => 10;
use Test::Exception;

{
    package Foo;
    use Moose;
    use Moose::Util::TypeConstraints;
    use MooseX::Params::Validate;

    subtype 'Size' => as 'Int' => where { $_ >= 0 };

    coerce 'Size' => from 'ArrayRef' => via { scalar @{$_} };

    sub bar {
        my $self   = shift;
        my %params = validated_hash(
            \@_,
            size1  => { isa => 'Size', coerce => 1 },
            size2  => { isa => 'Size', coerce => 0 },
            number => { isa => 'Num',  coerce => 1 },
        );
        [ $params{size1}, $params{size2}, $params{number} ];
    }

    sub baz {
        my $self = shift;
        my ( $size1, $size2, $number ) = validated_list(
            \@_,
            size1  => { isa => 'Size', coerce => 1 },
            size2  => { isa => 'Size', coerce => 0 },
            number => { isa => 'Num',  coerce => 1 },
        );
        [ $size1, $size2, $number ];
    }


    sub quux {
        my $self = shift;
        my ( $size1, $size2, $number ) = validated_list(
            \@_,
            size1  => { isa => 'Size', coerce => 1, optional => 1 },
            size2  => { isa => 'Size', coerce => 0, optional => 1 },
            number => { isa => 'Num',  coerce => 1, optional => 1 },
        );
        [ $size1, $size2, $number ];
    }
}

my $foo = Foo->new;
isa_ok( $foo, 'Foo' );

is_deeply(
    $foo->bar( size1 => 10, size2 => 20, number => 30 ),
    [ 10, 20, 30 ],
    'got the return value right without coercions'
);

is_deeply(
    $foo->bar( size1 => [ 1, 2, 3 ], size2 => 20, number => 30 ),
    [ 3, 20, 30 ],
    'got the return value right with coercions for size1'
);

throws_ok { $foo->bar( size1 => 30, size2 => [ 1, 2, 3 ], number => 30 ) }
qr/\QThe 'size2' parameter/,
    '... the size2 param cannot be coerced';

throws_ok { $foo->bar( size1 => 30, size2 => 10, number => 'something' ) }
qr/\QThe 'number' parameter/,
    '... the number param cannot be coerced';

is_deeply(
    $foo->baz( size1 => 10, size2 => 20, number => 30 ),
    [ 10, 20, 30 ],
    'got the return value right without coercions'
);

is_deeply(
    $foo->baz( size1 => [ 1, 2, 3 ], size2 => 20, number => 30 ),
    [ 3, 20, 30 ],
    'got the return value right with coercions for size1'
);

throws_ok { $foo->baz( size1 => 30, size2 => [ 1, 2, 3 ], number => 30 ) }
qr/\QThe 'size2' parameter/,
    '... the size2 param cannot be coerced';

throws_ok { $foo->baz( size1 => 30, size2 => 10, number => 'something' ) }
qr/\QThe 'number' parameter/,
    '... the number param cannot be coerced';

is_deeply(
    $foo->quux( size2 => 4 ),
    [ undef, 4, undef ],
    '... does not try to coerce keys which are not provided'
);
