<?php
/**
 * core.framework
 *
 * @category   Core
 * @package    Core_Form
 * @subpackage IntegrationTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 */

/**
 * @category   Core
 * @package    Core_Form
 * @subpackage IntegrationTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 * @group      Core_Form
 * @group      IntegrationTests
 */
class Core_Form_BasicFormLoadIntegrationTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Core_Form
     */
    protected $_object;

    /**
     * @var Core_Config
     */
    protected $_config;

    /**
     * @var Core_Loader_PluginLoader
     */
    protected $_pluginLoader;

    public function __construct()
    {
        // where is the file fixture?
        $path                = TESTS_ROOT .'/resources/fixtures/Core/Form/'. $this->_suiteName() .'.ini';
        $this->_config       = new Core_Config($path);
    }

    protected function setUp()
    {
        // for Core_Plugin_Manager
        Core_Application::getInstance()->getContainer()
                ->PluginLoader = new Core_Loader_PluginLoader;

        $this->_object = new Core_Form;
        $this->_object
            ->setConfig($this->_config);
    }

    /**
     * @covers Core_Form::getAttrib
     */
    public function testCanSetAttribs()
    {
        $this->assertEquals('g_h_123', $this->_object->getAttrib('class'));
    }

    /**
     * @covers Core_Form::__call
     */
    public function testCanLoadPlugin()
    {
        $this->assertTrue($this->_object->hasPlugin('persist'));
    }

    /**
     * @covers Core_Form::__call
     */
    public function testCanLoadGroup()
    {
        $this->assertTrue($this->_object->hasGroup('group1'));
    }

    /**
     * @covers Core_Form::getFullyQualifiedName
     */
    public function testCanNameGroup()
    {
        $this->assertEquals('group1', $this->_object->getGroup('group1')->getFullyQualifiedName());
    }

    /**
     * @covers Core_Form::getFullyQualifiedId
     */
    public function testCanIdentityGroup()
    {
        $this->assertEquals('my_form_group1', $this->_object->getGroup('group1')->getFullyQualifiedId());
    }

    /**
     * @covers Core_Form::__call
     */
    public function testCanLoadNestedGroup()
    {
        $this->assertTrue($this->_object->getGroup('group1')->hasGroup('group2'));
    }

    /**
     * @covers Core_Form::getFullyQualifiedName
     */
    public function testCanNameNestedGroup()
    {
        $group = $this->_object->getGroup('group1')->getGroup('group2');
        $this->assertEquals('group1[group2]', $group->getFullyQualifiedName());
    }

    /**
     * @covers Core_Form::getFullyQualifiedId
     */
    public function testCanIdentityNestedGroup()
    {
        $group = $this->_object->getGroup('group1')->getGroup('group2');
        $this->assertEquals('my_form_group1_group2', $group->getFullyQualifiedId());
    }

    /**
     * @covers Core_Form::__call
     */
    public function testCanLoadNestedElement()
    {
        $this->assertTrue($this->_object->getGroup('group1')->hasElement('element2'));
    }

    /**
     * @covers Core_Form::__call
     */
    public function testCanLoadDeepNestedElement()
    {
        $this->assertTrue($this->_object->getGroup('group1')->getGroup('group2')->hasElement('element3'));
    }

    /**
     * @covers Core_Form::__call
     */
    public function testCanLoadButton()
    {
        $this->assertTrue($this->_object->hasElement('element1'));
    }

    /**
     * @covers Core_Form_Element_Abstract::__call
     */
    public function testCanLoadFilter()
    {
        $element = $this->_object->getElement('element1');
        $this->assertTrue($element->hasFilter('trim'));
    }

    /**
     * @covers Core_Form_Element_Abstract::__call
     */
    public function testCanLoadValidator()
    {
        $element = $this->_object->getElement('element1');
        $this->assertTrue($element->hasValidator('identical'));
    }

    /**
     * @covers Core_Form::populate
     * @covers Core_Form_Element_Abstract::setValue
     */
    public function testCanPopulateElement()
    {
        $data = array(
            'element1' => 'foo',
        );
        $this->_object->populate($data);
        $element = $this->_object->getElement('element1');

        $this->assertEquals('foo', $element->getValue());
    }

    /**
     * @covers Core_Form::populate
     * @covers Core_Form_Element_Abstract::setValue
     */
    public function testCanPopulateNestedElement()
    {
        $data = array(
            'group1' => array(
                'element2' => 'foo',
            ),
            'garbage' => 'bla',
        );
        $this->_object->populate($data);
        $element = $this->_object->getGroup('group1')->getElement('element2');

        $this->assertEquals('foo', $element->getValue());
    }

    /**
     * @covers Core_Form::populate
     * @covers Core_Form_Element_Abstract::setValue
     */
    public function testCanPopulateDeppNestedElement()
    {
        $data = array(
            'group1' => array(
                'group2' => array(
                    'element3' => 'foo',
                ),
                'garbage' => 'bla',
            ),
            'garbage' => 'bla',
        );
        $this->_object->populate($data);
        $element = $this->_object->getGroup('group1')->getGroup('group2')->getElement('element3');

        $this->assertEquals('foo', $element->getValue());
    }

    /**
     * @covers Core_Form::getValues
     * @covers Core_Form_Element_Abstract::getValue
     */
    public function testCanFetchValuesFromVariousLevels()
    {
        $data = array(
            'group1' => array(
                'group2' => array(
                    'element3' => 'el3',
                    'garbage'  => 'bla',
                ),
                'element2' => 'el2',
                'garbage'  => 'bla',
            ),
            'element1' => 'el1',
            'garbage'  => 'bla',
        );
        $this->_object->populate($data);

        $this->assertEquals('el1', $this->_object->getElement('element1')->getValue());
        $this->assertEquals(array(
            'element3' => 'el3',
        ), $this->_object->getGroup('group1')->getGroup('group2')->getValues());
        $this->assertEquals(array(
            'group2' => array(
                'element3' => 'el3',
            ),
            'element2' => 'el2',
        ), $this->_object->getGroup('group1')->getValues());
        $this->assertEquals(array(
            'group1' => array(
                'group2' => array(
                    'element3' => 'el3',
                ),
                'element2' => 'el2',
            ),
            'element1' => 'el1',
        ), $this->_object->getValues());
    }

    /**
     * @covers Core_Form::isValid
     */
    public function testCanValidateForm()
    {
        $data = array(
            'group1' => array(
                'group2' => array(
                    // min = 10, fails validation
                    'element3' => 20,
                ),
            ),
        );
        $this->_object->populate($data);

        $this->assertFalse($this->_object->isValid());
    }

    /**
     * @covers Core_Form_Group_Abstract::isValid
     */
    public function testCanValidateGroup()
    {
        $data = array(
            'group1' => array(
                'group2' => array(
                    // min = 10, fails validation
                    'element3' => 20,
                ),
            ),
        );
        $this->_object->populate($data);

        $this->assertFalse($this->_object->getGroup('group1')->isValid());
    }

    /**
     * @covers Core_Form_Group_Abstract::isValid
     */
    public function testCanValidateNestedGroup()
    {
        $data = array(
            'group1' => array(
                'group2' => array(
                    // min = 10, fails validation
                    'element3' => 20,
                ),
            ),
        );
        $this->_object->populate($data);

        $this->assertFalse($this->_object->getGroup('group1')->getGroup('group2')->isValid());
    }

    /**
     * @covers Core_Form_Element_Abstract::isValid
     */
    public function testCanValidateElement()
    {
        $data = array(
            'group1' => array(
                'group2' => array(
                    // min = 10, fails validation
                    'element3' => 20,
                ),
            ),
        );
        $this->_object->populate($data);

        $this->assertFalse($this->_object->getGroup('group1')->getGroup('group2')->getElement('element3')->isValid());
    }

    /**
     * @covers Core_Form_Element_Abstract::getValue
     */
    public function testWillFilterElementRawValue()
    {
        $this->_object->populateRaw(array('element1' => '  aaa '));

        $this->assertEquals('aaa', $this->_object->getElement('element1')->getValue());
    }

    /**
     * @covers Core_Form_Element_Abstract::__clone
     */
    public function testCanCloneElement()
    {
        $clone = clone $this->_object->getElement('element1');
        $clone->setName('element2');
        $this->_object->addElement($clone);

        $this->assertNotSame($this->_object->getElement('element1'), $this->_object->getElement('element2'));

        // correct path
        $this->assertEquals(
            'element2',
            $this->_object->getElement('element2')->getFullyQualifiedName()
        );
    }

    /**
     * @covers Core_Form_Element_Abstract::__clone
     */
    public function testCanCloneGroup()
    {
        $clone = clone $this->_object->getGroup('group1');
        $clone->setName('group2');
        $this->_object->addGroup($clone);

        // group is cloned
        $this->assertNotSame($this->_object->getGroup('group1'), $this->_object->getGroup('group2'));

        // elements are cloned
        $this->assertNotSame(
            $this->_object->getGroup('group1')->getElement('element2'),
            $this->_object->getGroup('group2')->getElement('element2')
        );

        // correct plugin manager owner
        $this->assertSame($clone, $clone->getPluginManager()->getOwner());

        // correct path
        $this->assertEquals(
            'group2[element2]',
            $this->_object->getGroup('group2')->getElement('element2')->getFullyQualifiedName()
        );

        // correct ID
        $this->assertEquals(
            'my_form_group2_element2',
            $this->_object->getGroup('group2')->getElement('element2')->getFullyQualifiedId()
        );
    }

    /**
     * @covers Core_Form_Element_Abstract::__clone
     */
    public function testCanCloneForm()
    {
        $object = clone $this->_object;
        $object->setName('subForm');
        $this->_object->addGroup($object);

        // form inside a form
        $this->assertEquals(array(
            'group1'   => array(
                'group2'   => array(
                    'element3' => '',
                ),
                'element2' => ''
            ),
            'subForm'  => array(
                'group1'   => array(
                    'group2'   => array(
                        'element3' => '',
                    ),
                    'element2' => ''
                ),
                'element1' => '',
            ),
            'element1' => '',
        ), $this->_object->getValues());
    }

    /**
     * @covers Core_Form_Element_Abstract::isValid
     */
    public function testWillObeyRequired()
    {
        $element = $this->_object->getElement('element1');
        $this->assertFalse($element->isValid());
        $element->setValue('foo');
        $this->assertTrue($element->isValid());
    }

    protected function _suiteName()
    {
        return strtolower(basename(__FILE__, 'IntegrationTest.php'));
    }
}
