<?php  

// 3rd party libraries
require_once('../../../concrete/libraries/3rdparty/adodb/adodb.inc.php');
require_once('../libraries/3rdparty/simpletest/autorun.php');

// And the class to test
require_once('../models/tree_model_base.php');

class TestBaseTree extends UnitTestCase
{
	private $db;
	
	private $tableName = 'btFileTreeNodesTest';
	private $tree;

	function __construct()
	{
		$this->db = ADONewConnection('mysql://root@localhost/iso');
		$this->db->SetFetchMode(ADODB_FETCH_ASSOC);
	}

	function setUp()
	{
		$this->db->Execute($this->setUpSql());
		$this->tree = new TreeModelBase(1, $this->db, $this->tableName);
    }
    
    function tearDown()
    {
		$this->db->Execute("DROP TABLE $this->tableName");
    }
    
    function setUpSql()
    {
    	return "
		CREATE TABLE $this->tableName (
           `id` int(10) unsigned NOT NULL auto_increment,
           `bID` int(10) unsigned NOT NULL,
           `name` varchar(200) collate utf8_swedish_ci NOT NULL,
           `lft` int(10) unsigned NOT NULL,
           `rgt` int(10) unsigned NOT NULL,
           PRIMARY KEY  (`id`),
           KEY `bID` (`bID`),
           KEY `lft` (`lft`),
           KEY `rgt` (`rgt`)
         )";
    }
    
	///// Tests /////////////////////////////////////////////////////
	
	function testAddNodesOnEmptyTree()
	{
		// Arrange
		
		// Act
		$check = $this->tree->AddNode('Test1', 0, false);
		
		// Assert
		$this->assertTrue($check);

		$table = $this->tree->DisplayNode(0);		
		$this->assertEqual($table, array ( 0 => array ( 'id' => '1', 'name' => 'Test1', 'depth' => '0', 'leaf' => '1', )));
	}
	
	function testAddChildNodes()
	{
		// Arrange
		$this->tree->AddNode('Test1', 0, false);
		
		// Act
		$check = $this->tree->AddNode('Child1', 1, true);
		$check = $this->tree->AddNode('Child2', 2, true);
		$check = $this->tree->AddNode('Child3', 3, true);
		
		// Assert
		$table = $this->tree->DisplayNode(0);				
		$this->assertEqual($table[0], array ( 'id' => '1', 'name' => 'Test1', 'depth' => '0', 'leaf' => '0'));
		$this->assertEqual($table[1], array ( 'id' => '2', 'name' => 'Child1', 'depth' => '1', 'leaf' => '0'));
		$this->assertEqual($table[2], array ( 'id' => '3', 'name' => 'Child2', 'depth' => '2', 'leaf' => '0'));
		$this->assertEqual($table[3], array ( 'id' => '4', 'name' => 'Child3', 'depth' => '3', 'leaf' => '1'));
	}
	
	function testAddSiblingAndChildNodes()
	{
		// Arrange
		$this->tree->AddNode('Test1', 0, false);
		
		// Act
		$this->tree->AddNode('Sibling1', 1, false);
		$this->tree->AddNode('Sibling2', 2, false);
		$this->tree->AddNode('Sibling3', 3, false);		
		$this->tree->AddNode('Child1', 3, true);
		
		// Assert
		$table = $this->tree->DisplayNode(0);				
		$this->assertEqual($table[0], array ( 'id' => '1', 'name' => 'Test1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[1], array ( 'id' => '2', 'name' => 'Sibling1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[2], array ( 'id' => '3', 'name' => 'Sibling2', 'depth' => '0', 'leaf' => '0'));
		$this->assertEqual($table[3], array ( 'id' => '5', 'name' => 'Child1', 'depth' => '1', 'leaf' => '1'));
		$this->assertEqual($table[4], array ( 'id' => '4', 'name' => 'Sibling3', 'depth' => '0', 'leaf' => '1'));

		// Test display only part of tree
		$table = $this->tree->DisplayNode(3);
		$this->assertEqual($table[0], array ( 'id' => '3', 'name' => 'Sibling2', 'depth' => '0', 'leaf' => '0'));
		$this->assertEqual($table[1], array ( 'id' => '5', 'name' => 'Child1', 'depth' => '1', 'leaf' => '1'));
	}

	function testRenameNodes()
	{
		// Arrange
		$this->tree->AddNode('Test1', 0, false);
		$this->tree->AddNode('Sibling1', 1, false);

		// Act
		$this->tree->RenameNode(1, 'Test2');
		$this->tree->RenameNode(2, 'Sibling2');
		
		// Assert
		$table = $this->tree->DisplayNode(0);				
		$this->assertEqual($table[0], array ( 'id' => '1', 'name' => 'Test2', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[1], array ( 'id' => '2', 'name' => 'Sibling2', 'depth' => '0', 'leaf' => '1'));
	}
	
	function testDeleteNodeTree()
	{
		// Arrange
		$this->tree->AddNode('Test1', 0, false);
		$this->tree->AddNode('Sibling1', 1, false);
		$this->tree->AddNode('Sibling2', 2, false);
		$this->tree->AddNode('Sibling3', 1, false);		
		$this->tree->AddNode('Child1', 3, true);
		
		// Act
		$this->tree->DeleteNode(3, true);
		
		// Assert
		$table = $this->tree->DisplayNode(0);				
		$this->assertEqual($table[0], array ( 'id' => '1', 'name' => 'Test1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[1], array ( 'id' => '4', 'name' => 'Sibling3', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[2], array ( 'id' => '2', 'name' => 'Sibling1', 'depth' => '0', 'leaf' => '1'));
	}

	function testDeleteNodeButNotChildren()
	{
		// Arrange
		$this->tree->AddNode('Test1', 0, false);
		$this->tree->AddNode('Sibling1', 1, false);
		$this->tree->AddNode('Sibling2', 2, false);
		$this->tree->AddNode('Sibling3', 3, false);
		$this->tree->AddNode('Child1', 3, true);
		
		// Act
		$this->tree->DeleteNode(3);
		
		// Assert
		$table = $this->tree->DisplayNode(0);				
		$this->assertEqual($table[0], array ( 'id' => '1', 'name' => 'Test1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[1], array ( 'id' => '2', 'name' => 'Sibling1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[2], array ( 'id' => '5', 'name' => 'Child1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[3], array ( 'id' => '4', 'name' => 'Sibling3', 'depth' => '0', 'leaf' => '1'));
	}
	
	function testDeleteNonExistingNode()
	{
		// Arrange
		$this->expectException(new Exception('nodeId 3 not found in table.'));
		
		// Act
		$this->tree->DeleteNode(3, true);
		
		// Assert
	}
	
	function testMoveNodeTreeToChild()
	{
		// Arrange
		$this->tree->AddNode('Test1', 0, false);
		$this->tree->AddNode('Sibling1', 1, false);
		$this->tree->AddNode('Sibling2', 2, false);
		$this->tree->AddNode('Sibling3', 3, false);		
		$this->tree->AddNode('Child1', 4, true);
		
		// Act
		$this->tree->MoveNode(4, 2, true);
		
		// Assert
		$table = $this->tree->DisplayNode(0);				
		$this->assertEqual($table[0], array ( 'id' => '1', 'name' => 'Test1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[1], array ( 'id' => '2', 'name' => 'Sibling1', 'depth' => '0', 'leaf' => '0'));
		$this->assertEqual($table[2], array ( 'id' => '4', 'name' => 'Sibling3', 'depth' => '1', 'leaf' => '0'));
		$this->assertEqual($table[3], array ( 'id' => '5', 'name' => 'Child1', 'depth' => '2', 'leaf' => '1'));
		$this->assertEqual($table[4], array ( 'id' => '3', 'name' => 'Sibling2', 'depth' => '0', 'leaf' => '1'));
	}	
	
	function testMoveNodeTreeToTop()
	{
		// Arrange
		$this->tree->AddNode('Test1', 0, false);
		$this->tree->AddNode('Sibling1', 1, false);
		$this->tree->AddNode('Sibling2', 2, false);
		$this->tree->AddNode('Sibling3', 3, false);		
		$this->tree->AddNode('Child1', 4, true);
		
		// Act
		$this->tree->MoveNode(4, 0, false);
		
		// Assert
		$table = $this->tree->DisplayNode(0);				
		$this->assertEqual($table[0], array ( 'id' => '4', 'name' => 'Sibling3', 'depth' => '0', 'leaf' => '0'));
		$this->assertEqual($table[1], array ( 'id' => '5', 'name' => 'Child1', 'depth' => '1', 'leaf' => '1'));
		$this->assertEqual($table[2], array ( 'id' => '1', 'name' => 'Test1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[3], array ( 'id' => '2', 'name' => 'Sibling1', 'depth' => '0', 'leaf' => '1'));
		$this->assertEqual($table[4], array ( 'id' => '3', 'name' => 'Sibling2', 'depth' => '0', 'leaf' => '1'));
	}	
}
