<?php
/**
 * Copyright 2018 Kacper Donat
 *
 * @author Kacper "Kadet" Donat <kacper@kadet.net>
 *
 * Full license available in separate LICENSE file
 */

use \Kadet\Functional as f;
use const Kadet\Functional\_;

function subtract($a, $b) {
    return $a - $b;
}

class PartialApplicationTest extends \PHPUnit\Framework\TestCase
{
    public function testPartialApplicationOfOneArgument()
    {
        $applied = f\partial('subtract', 10);

        $this->assertEquals(0, $applied(10));
        $this->assertEquals(10, $applied(0));
        $this->assertEquals(20, $applied(-10));
    }

    public function testPartialApplicationOfAllArguments()
    {
        $applied = f\partial('subtract', 10, 20);

        $this->assertEquals(-10, $applied());
    }

    public function testPartialApplicationOfFewArguments()
    {
        $applied = f\partial('array_merge', ['a'], ['b'], ['c']);

        $this->assertEquals(['a', 'b', 'c', 'd', 'e'], $applied(['d'], ['e']));
    }

    public function testPartialApplicationWithPlaceholders()
    {
        $applied = f\partial('array_merge', ['a'], _, ['c']);

        $this->assertEquals(['a', 'd', 'c'], $applied(['d']));
    }

    public function testPartialApplicationOfAppliedFunction()
    {
        $applied = f\partial('array_merge', ['a'], _, ['c']);
        $double  = f\partial($applied, _, ['d']);

        $this->assertEquals(['a', 'b', 'c', 'd', 'e'], $double(['b'], ['e']));
    }

    public function testDecoration()
    {
        $x = function() {};
        $applied = f\partial($x);

        $this->assertSame($applied->getDecorated(), $x);
    }

    public function testArgumentProviding()
    {
        $applied = f\partial('array_merge', ['a'], _, ['c']);

        $this->assertSame(
            [0 => ['a'], 2 => ['c']],
            $applied->getArguments()
        );
    }
}