#!perl

use Test::More tests => 25;

use warnings FATAL => 'all';
use strict;

use Function::Parameters { fun => 'function_strict', method => 'method_strict' };

{
	package Foo;

	method new($class : ) {
		return bless {
			x => 1,
			y => 2,
			z => 3,
		}, $class;
	}

	method get_x()       { $self->{x} }
	method get_y($self:) { $self->{y} }
	method get_z($this:) { $this->{z} }

	method set_x($val)        { $self->{x} = $val; }
	method set_y($self:$val)  { $self->{y} = $val; }
	method set_z($this: $val) { $this->{z} = $val; }
}

my $o = Foo->new;
ok $o->isa('Foo'), "Foo->new->isa('Foo')";

is $o->get_x, 1;
is $o->get_y, 2;
is $o->get_z, 3;

$o->set_x("A");
$o->set_y("B");
$o->set_z("C");

is $o->get_x, "A";
is $o->get_y, "B";
is $o->get_z, "C";

is eval { $o->get_z(42) }, undef;
like $@, qr/many arguments/;

is eval { $o->set_z }, undef;
like $@, qr/enough arguments/;

is eval q{fun ($self:) {}}, undef;
like $@, qr/invocant/;

is eval q{fun ($x : $y) {}}, undef;
like $@, qr/invocant/;

is eval q{method (@x:) {}}, undef;
like $@, qr/invocant/;

is eval q{method (%x:) {}}, undef;
like $@, qr/invocant/;

{
	use Function::Parameters {
		def => {
			invocant => 1,
		}
	};

	def foo1($x) { join ' ', $x, @_ }
	def foo2($x: $y) { join ' ', $x, $y, @_ }
	def foo3($x, $y) { join ' ', $x, $y, @_ }

	is foo1("a"), "a a";
	is foo2("a", "b"), "a b b";
	is foo3("a", "b"), "a b a b";
	is foo1("a", "b"), "a a b";
	is foo2("a", "b", "c"), "a b b c";
	is foo3("a", "b", "c"), "a b a b c";
}
