<?php

class Wact_Template_Compiler_Parser_State_ComponentTestCase extends Wact_Template_Compiler_Parser_State_Test {

    protected $component;
    protected $context;

    function setUp() {
        parent::setUp();

        $this->component = new MockViewTemplateNode($this);

        $this->treeBuilder->component = $this->component;
        $this->treeBuilder->setReturnValue('buildComponent', $this->component);
        $this->treeBuilder->setReturnValue('getCursor', $this->component);

        $this->context = new MockCompilingContext($this);
        $this->state = new Wact_Template_Compiler_Parser_State_Component($this->parser, $this->treeBuilder, $this->context);

        $this->state->setDocumentLocator($this->locator);
    }

    function tearDown() {
        unset($this->component);
        unset($this->state);
    }

    function testStartElementIsPlain() {
        $tag = 'test';
        $attrs = array('foo'=>'bar');

        $this->treeBuilder->expectOnce('pushTag', array($tag));

        $this->state->startElement($tag, $attrs);

        $this->treeBuilder->tally();
    }

    function testStartElementIsComponent() {
        $tag = 'test';
        $attrs = array('foo'=>'bar', 'wact:id' => 'foo');

        $this->context->setReturnValue('getTagInfo', FALSE);

        $this->component->setReturnValue('preParse', Wact_Template_Compiler_Node::REQUIRE_PARSING);

        $this->treeBuilder->expectOnce('buildComponent', array('*', $tag, $attrs, Wact_Template_Compiler_Node::CLOSING_TAG));
        $this->treeBuilder->expectNever('pushTag');

        $this->state->startElement($tag, $attrs);

        $this->treeBuilder->tally();
    }

    function testStartElementLiteral() {
        $tag = 'test';
        $attrs = array('foo'=>'bar', 'wact:id' => 'foo');

        $this->context->setReturnValue('getTagInfo', FALSE);

        $this->component->setReturnValue('preParse', Wact_Template_Compiler_Node::FORBID_PARSING);
        $this->treeBuilder->setReturnValue('pushNode', Wact_Template_Compiler_Node::FORBID_PARSING);

        $this->parser->expectOnce('changeToLiteralParsingState', array($tag));

        $this->state->startElement($tag, $attrs);

        $this->parser->tally();
    }

    function testStartElementEndtagForbidden() {
        $tag = 'test';
        $attrs = array('foo'=>'bar', 'wact:id' => 'foo');

        $info = new Wact_Template_Compiler_Generic_Info('test', Wact_Template_Compiler_Tag_Info::ENDTAG_FORBIDDEN);
        $this->context->setReturnValue('getTagInfo', $info);

        $this->component->setReturnValue('preParse', Wact_Template_Compiler_Node::REQUIRE_PARSING);

        $this->treeBuilder->expectNever('pushTag');

        $this->parser->expectNever('changeToLiteralParsingState');

        $this->state->startElement($tag, $attrs);

        $this->treeBuilder->tally();
        $this->parser->tally();
    }

    function testStartElementIllegalAttributeName() {
        $tag = 'test';
        $attrs = array('wact:id'=>'{$hello}');

        try {
            $this->state->startElement($tag, $attrs);
            $this->fail('Expected exception not thrown');
        } catch (Wact_Exception_Base $e) {
            $this->pass();
        }
    }

    function testEndElementIsComponent() {
        $tag = 'test';

        $this->treeBuilder->expectOnce('popTag', array($tag));
        $this->treeBuilder->setReturnValue('popTag', TRUE);

        $this->state->endElement($tag);

        $this->treeBuilder->tally();
    }

    function testEndElementisPlain() {
        $tag = 'test';
        $raw = '</'.$tag.'>';
        $this->treeBuilder->expectOnce('popTag', array($tag));
        $this->treeBuilder->setReturnValue('popTag', FALSE);
        $this->locator->setReturnValue('getRawEventString', $raw);
        $this->treeBuilder->expectOnce('addTextNode', array($raw));

        $this->state->endElement($tag);

        $this->treeBuilder->tally();
    }


    function testEndElementNoMatch() {

        $component = new Wact_Template_Compiler_Node('bar', NULL, new Wact_Template_Compiler_Location('file', 123));

        $this->treeBuilder = new Wact_Template_Compiler_Parser_TreeBuilder(NULL);
        $this->treeBuilder->setCursor($component);
        $this->treeBuilder->setDocumentLocator($this->locator);
        $this->treeBuilder->pushTag('foo');

        $this->state = new Wact_Template_Compiler_Parser_State_Component($this->parser, $this->treeBuilder, $this->context);
        $this->state->setDocumentLocator($this->locator);

        $this->state->endElement('bar');

        unset($treeBuilder);
    }

    function testEndElementForbidden() {
        $tag = 'test';

        $info = new Wact_Template_Compiler_Generic_Info('test', Wact_Template_Compiler_Tag_Info::ENDTAG_FORBIDDEN);
        $this->context->setReturnValue('getTagInfo', $info);

        try {
            $this->state->endElement($tag);
            $this->fail('Expected exception not thrown');
        } catch (Wact_Template_Compiler_Exception $e) {
            $this->pass();
            $this->assertEqual($e->getTag(), 'test');
        }
    }

    function testEmptyElement() {
        $tag = 'test';
        $attrs = array('foo'=>'bar');

        // $this->context->setReturnValue('findComponent', NULL);

        $this->treeBuilder->expectNever('pushTag');

        $this->state->emptyElement($tag, $attrs);
        $this->treeBuilder->tally();
    }

    function testEmptyElementIsComponent() {
        $tag = 'test';
        $attrs = array('foo'=>'bar', 'wact:id' => 'foo');

        $this->context->setReturnValue('getTagInfo', FALSE);

        $this->component->setReturnValue('preParse', Wact_Template_Compiler_Node::REQUIRE_PARSING);

        $this->treeBuilder->expectOnce('buildComponent', array('*', $tag, $attrs, Wact_Template_Compiler_Node::CLOSING_SELF));
        $this->treeBuilder->expectNever('pushNode');
        $this->treeBuilder->expectNever('pushTag');

        $this->state->emptyElement($tag, $attrs);

        $this->treeBuilder->tally();
    }

    function testEmptyElementLiteral() {
        $tag = 'test';
        $attrs = array('foo'=>'bar', 'wact:id' => 'foo');

        $this->context->setReturnValue('getTagInfo', FALSE);

        $this->component->setReturnValue('preParse', Wact_Template_Compiler_Node::FORBID_PARSING);

        $this->treeBuilder->setReturnValue('pushNode', Wact_Template_Compiler_Node::FORBID_PARSING);

        $this->parser->expectNever('changeToLiteralParsingState');

        $this->state->emptyElement($tag,$attrs);

        $this->parser->tally();
    }

    function testEmptyElementEndtagForbidden() {
        $tag = 'test';
        $attrs = array('foo'=>'bar', 'wact:id' => 'foo');

        $info = new Wact_Template_Compiler_Generic_Info('test', Wact_Template_Compiler_Tag_Info::ENDTAG_FORBIDDEN);
        $this->context->setReturnValue('getTagInfo', $info);

        $this->component->setReturnValue('preParse', Wact_Template_Compiler_Node::REQUIRE_PARSING);

        $this->state->emptyElement($tag, $attrs);

        $this->treeBuilder->tally();
    }

    function testEmptyElementIllegalAttributeName() {
        $tag = 'test';
        $attrs = array('wact:id'=>'{$hello}');

        try {
            $this->state->emptyElement($tag, $attrs);
            $this->fail('Expected exception not thrown');
        } catch (Wact_Exception_Base $e) {
            $this->pass();
        }
    }

    function testCharacters() {
        $text = 'test';
        $this->treeBuilder->expectOnce('addContent', array($text));
        $this->state->characters($text);
    }

    function testComment() {
        $text = 'test';
        $raw = '<!--' . $text . '-->';
        $this->locator->setReturnValue('getRawEventString', $raw);
        $this->treeBuilder->expectOnce('addContent', array($raw));
        $this->state->comment($text);
    }

/*
    function testGetTagInfo() {
        $this->assertIsA($this->dict->getPluginInfo('TeStTag'), 'Wact_Template_Compiler_Tag_Info');
    }

    function testNotATag() {
        $knownParent = new Wact_Template_Compiler_Node_TagView(NULL, NULL, NULL);
        $tag = 'notatag';
        $attrs = array();
        $this->assertFalse($this->dict->findComponent($tag, $attrs, FALSE, $knownParent));
    }

    function testRunatEqualsClient() {
        $knownParent = new Wact_Template_Compiler_Node_TagView(NULL, NULL, NULL);
        $tag = 'foo';
        $attrs = array('runat'=>'client');
        $this->assertNull($this->dict->findComponent($tag, $attrs, FALSE, $knownParent));
    }

    function testComponentWithRunatServer() {
        $knownParent = new Wact_Template_Compiler_Node_TagView(NULL, NULL, NULL);
        $this->dict->registerPlugin(new Wact_Template_Compiler_Tag_Info('isatag', 'blah'), 'example.php');
        $tag = 'iSaTag';
        $attrs = array('runat'=>'server');
        $this->assertIsA($this->dict->findComponent($tag, $attrs, FALSE, $knownParent), 'Wact_Template_Compiler_Tag_Info');
    }

    function testGenericTag() {
        $knownParent = new Wact_Template_Compiler_Node_TagView(NULL, NULL, NULL);
        $tag = 'iSaGenericTag';
        $attrs = array('wact:id' => Wact_Template_Compiler_Attribute::WACT_ID_UNSPECIFIC);
        $this->assertIsA($this->dict->findComponent($tag, $attrs, TRUE, $knownParent), 'Wact_Template_Compiler_Tag_Info');
    }

    function testGenericContainerTag() {
        $knownParent = new Wact_Template_Compiler_Node_TagView(NULL, NULL, NULL);
        $tag = 'iSaGenericContainerTag';
        $attrs = array('wact:id'=>Wact_Template_Compiler_Attribute::WACT_ID_UNSPECIFIC);
        $this->assertIsA($this->dict->findComponent($tag, $attrs, FALSE, $knownParent), 'Wact_Template_Compiler_Tag_Info');
    }
*/

}

?>