<?php

class Wact_Php_Writer_ClassTestCase extends Wact_Test_Case {
    function testGetName() {
        $name = 'MyView';
        $class = new Wact_Php_Writer_Class($name);
        $this->assertEqual($class->getName(), $name);
    }

    function testEmpty() {
        $class = new Wact_Php_Writer_Class('MyView');
        $this->assertEqual($class->getName(), 'MyView');
        $this->assertEqual($class->getCode(), 'class MyView {' . "\n\n" . '}' . "\n");
    }

    function testImplements() {
        $class = new Wact_Php_Writer_Class('MyView', null, 'TestInterface');
        $this->assertEqual($class->getName(), 'MyView');
        $this->assertEqual($class->getCode(), 'class MyView implements TestInterface {' . "\n\n" . '}' . "\n");
    }

    function testExtends() {
        $class = new Wact_Php_Writer_Class('MyView', 'Wact_View_Root');
        $this->assertEqual($class->getName(), 'MyView');
        $this->assertEqual($class->getCode(), 'class MyView extends Wact_View_Root {' . "\n\n" . '}' . "\n");
    }

    function testExtendsImplements() {
        $class = new Wact_Php_Writer_Class('MyView', 'Wact_View_Root', 'TestInterface');
        $this->assertEqual($class->getName(), 'MyView');
        $this->assertEqual($class->getCode(), 'class MyView extends Wact_View_Root implements TestInterface {' . "\n\n" . '}' . "\n");
    }

    function testRegisterFunction() {
        $class = new Wact_Php_Writer_Class('MyView');

        $name = 'render';
        $method = new Wact_Php_Writer_Method($name);
        $methodName = $class->registerMethod($method);
        $this->assertEqual($name, $methodName);

        try {
            $class->registerMethod($method);
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        $method2 = $class->findMethod('render');
        $this->assertIdentical($method, $method2);

        $this->assertEqual($class->getCode(), 'class MyView {' . "\n\n" . 'function render() {' . "\n\n" . '}' . "\n\n" . '}' . "\n");
    }

    function testRegisterProperty() {
        $class = new Wact_Php_Writer_Class('MyView');

        $name = 'myVar';
        $prop = new Wact_Php_Writer_Property($name);

        $class->registerProperty($prop);

        try {
            $class->registerProperty($prop);
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        $prop2 = $class->findProperty($name);
        $this->assertIdentical($prop, $prop2);

        $this->assertEqual($class->getCode(), 'class MyView {' . "\n\n" . $prop->getDeclaration() . "\n\n" . '}' . "\n");
    }

    function testSwitchTo() {
        $class = new Wact_Php_Writer_Class('MyView');

        try {
            $class->switchToPHP();
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        try {
            $class->switchToHTML();
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        $method = new Wact_Php_Writer_Method('render');
        $class->registerMethod($method);

        $class->switchToPHP();
        $class->switchToHTML();
        $class->switchToHTML();
        $class->switchToPHP();
        $class->switchToPHP();

        $body = ' ?' . '><' . '?php ';
        $this->assertEqual($class->getCode(), 'class MyView {' . "\n\n" . 'function render() {' . "\n" . $body . "\n" . '}' . "\n\n" . '}' . "\n");
    }

    function testScopeWrites() {
        $class = new Wact_Php_Writer_Class('MyView');

        $method = new Wact_Php_Writer_Method('render');
        $class->registerMethod($method);

        $class->writePHP('if ($x = ');
        $class->writePHPLiteral('f\'o\'o');
        $class->writePHP(') { ');
        $class->writeHTML('bar');
        $class->writePHP('}');

        $body = 'if ($x = \'f\\\'o\\\'o\') {  ?' . '>bar<' . '?php }';
        $this->assertEqual($class->getCode(), 'class MyView {' . "\n\n" . 'function render() {' . "\n" . $body . "\n" . '}' . "\n\n" . '}' . "\n");
    }

    function testSwitchToMethodScope() {
        $class = new Wact_Php_Writer_Class('MyView');

        $method = new Wact_Php_Writer_Method('render');
        $class->registerMethod($method);
        // don't switch scope here (registerFunction() should do it automatically)
        $class->writePHP('echo 1;');

        $method = new Wact_Php_Writer_Method('render2');
        $class->registerMethod($method);

        $class->switchToMethodScope('render2');
        $class->writePHP('echo 2;');

        $class->switchToMethodScope('render');
        $class->writePHP('echo 1;');

        try {
            $class->switchToMethodScope('nonexistant');
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        $func1 = 'function render() {' . "\necho 1;echo 1;\n" . '}' . "\n\n";
        $func2 = 'function render2() {' . "\necho 2;\n" . '}' . "\n\n";
        $this->assertEqual($class->getCode(), 'class MyView {' . "\n\n" . $func1 . $func2 . '}' . "\n");
    }

    function testSwitchToGlobalScope() {
        $class = new Wact_Php_Writer_Class('MyView');

        $method = new Wact_Php_Writer_Method('render');
        $class->registerMethod($method);

        $class->switchToMethodScope(NULL);

        try {
            $class->writePHP('This will never be written into the result');
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        try {
            $class->writePHPLiteral('This will never be written into the result');
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        try {
            $class->writeHTML('This will never be written into the result');
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }
    }

    function testSetScope() {
        $class = new Wact_Php_Writer_Class('MyView');

        $class->createMethod('render');
        $renderFunc = $class->findMethod('render');

        $class->createMethod('paint');
        $paintFunc = $class->findMethod('paint');

        $scope = $class->switchToMethodScope('render');
        $this->assertIdentical($scope, $paintFunc);

        $scope = $class->setScope($scope);
        $this->assertIdentical($scope, $renderFunc);

        $scope = $class->setScope($scope);
        $this->assertIdentical($scope, $paintFunc);
    }

    function testSwitchScopeReturns() {
        $class = new Wact_Php_Writer_Class('MyView');

        $class->createMethod('render');
        $renderFunc = $class->findMethod('render');

        $scope = $class->switchToMethodScope(null);
        $this->assertIdentical($scope, $renderFunc);

        $scope = $class->switchToMethodScope('render');
        $this->assertNull($scope);
    }

    function testCreateFunction() {
        $class = new Wact_Php_Writer_Class('MyClass');

        $name = 'init';
        $params = '$p1';

        $methodName = $class->createMethod($name, $params);
        $method = $class->findMethod($methodName);
        $this->assertEqual($method->getName(), $name);
        $this->assertEqual($method->getParams(), $params);
        $this->assertIdentical($method, $class->findMethod($name));

        try {
            $method = $class->createMethod($name, $params);
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        $method->writePHP('echo 1;');
        $class->writePHP('echo 2;');

        $funcst = 'function ' . $name . '(' . $params . ') {' . "\n" . 'echo 1;echo 2;' . "\n" . '}';
        $this->assertEqual($class->getCode(), 'class MyClass {' . "\n\n" . $funcst . "\n\n" . '}' . "\n");
    }

    function testCreateProperty() {
        $class = new Wact_Php_Writer_Class('MyView');

        $name = 'myVar';
        $value = '123';
        $visibility = 'protected';

        $stringref = $class->createProperty($name, $value, $visibility);
        $this->assertEqual($stringref, 'myVar');

        $property = $class->findProperty($name);
        $this->assertEqual($property->getName(), $name);

        try {
            $property = $class->createProperty($name, $value);
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        $this->assertEqual($class->getCode(), 'class MyView {' . "\n\n" . $property->getDeclaration() . "\n\n" . '}' . "\n");
    }

    function testCreateTempProperty() {
        $class = new Wact_Php_Writer_Class('MyView');
        $propertyName = $class->createTempProperty();
        $this->assertWantedPattern('/[a-z][a-z0-9]*/i', $propertyName);
    }

    function testCreateSecondTempProperty() {
        $class = new Wact_Php_Writer_Class('MyView');
        $var = $class->createTempProperty();
        $A = $class->createTempProperty();
        $B = $class->createTempProperty();
        $this->assertNotEqual($A, $B);
    }

    function testCreateTempProperties() {
        $class = new Wact_Php_Writer_Class('MyView');
        for ($i = 1; $i <= 30; $i++) {
            $propertyName = $class->createTempProperty();
            $this->assertWantedPattern('/[a-z][a-z0-9]*/i', $propertyName);
        }
    }

    function testCreateTempVariable() {
        $class = new Wact_Php_Writer_Class('MyView');

        try {
            $var = $class->createTempVariable();
            $this->fail('Expected exception not thrown');
        } catch (Wact_Php_Writer_Exception $e) {
            $this->pass();
        }

        $class->createMethod('init');

        $var = $class->createTempVariable();

        $this->assertWantedPattern('/[a-z][a-z0-9]*/i', $var);
    }

}

?>