<?php
/**
 * OpenSQLManager
 *
 * Free Database manager for Open Source Databases
 *
 * @author 		Timothy J. Warren
 * @copyright	Copyright (c) 2012
 * @link 		https://github.com/aviat4ion/OpenSQLManager
 * @license 	http://philsturgeon.co.uk/code/dbad-license
 */

// --------------------------------------------------------------------------

/**
 * Tabbed Container for database properties
 */
class DB_tabs extends GTKNotebook {

	/**
	 * Current Tab Widget object
	 * @var DB_Tabs
	 */
	private static $instance;
	private $data;

	/**
	 * Return the db tabs object if it exists, or create and return
	 *
	 * @return DB_tabs
	 */
	public static function &get_instance()
	{
		if (empty(self::$instance))
		{
			self::$instance = new DB_tabs();
		}

		return self::$instance;
	}

	// --------------------------------------------------------------------------

	/**
	 * Create the object
	 */
	public function __construct()
	{
		parent::__construct();
		$this->data = new StdClass();
	}

	// --------------------------------------------------------------------------

	/**
	 * Add a new tab with the provided label
	 *
	 * @param string $label
	 * @param GObject $widget
	 * @return void
	 */
	public function add_tab($label, $widget = NULL)
	{
		if (is_null($widget))
		{
			$widget = new Data_Grid();
		}

		$this->append_page($widget, new GtkLabel($label));
	}

	// --------------------------------------------------------------------------

	/**
	 * Create popup window with table data
	 *
	 * @param GTKTreeView $view
	 * @param array $path
	 * @param GtkTreeviewColumn $col
	 * @param Query_Builder $conn
	 * @return void
	 */
	public function show_table_data($view, $path, $col, &$conn)
	{
		$table = $view->get(0);

		$query = $conn->get($table);
		$data = $query->fetchAll(PDO::FETCH_ASSOC);

		return new DB_Table_data($data);
	}

	// --------------------------------------------------------------------------

	/**
	 * Create tabs for database aspects
	 *
	 * @param Query_Builder $conn
	 * @return void
	 */
	public static function get_db_tabs(&$conn)
	{
		// Empty the tabs
		self::reset();
		self::$instance->hide_all();

		// 'Databases' Tab
		self::_add_tab($conn, 'Databases', 'Db Name', 'get_dbs');

		// 'Schemas' Tab
		self::_add_tab($conn, 'Schemas', 'Schema Name', 'get_schemas');

		// 'Tables' Tab
		self::_add_tab($conn, 'Tables', 'Table Name', 'get_tables', array(
			array(
				'row-activated',
				array(self::$instance, 'show_table_data'),
				$conn
			)
		));

		// 'System Tables' Tab
		self::_add_tab($conn, 'System Tables', 'Table Name', 'get_system_tables', array(
			array(
				'row-activated',
				array(self::$instance, 'show_table_data'),
				$conn
			)
		));

		// 'Views' Tab
		self::_add_tab($conn, 'Views', 'View Name', 'get_views', array(
			array(
				'row-activated',
				array(self::$instance, 'show_table_data'),
				$conn
			)
		));

		// 'Sequences' Tab
		self::_add_tab($conn, 'Sequences', 'Sequence Name', 'get_sequences');

		// 'Triggers' Tab
		self::_add_row_tab($conn, 'Triggers','get_triggers');

		// 'Procedures' Tab
		self::_add_row_tab($conn, 'Procedures', 'get_procedures');

		// 'Functions' Tab
		self::_add_row_tab($conn, 'Functions', 'get_functions');

		// Show the tabs
		self::$instance->show_all();

	}

	// --------------------------------------------------------------------------

	/**
	 * Remove current tabs
	 *
	 * @param string $conn_name
	 * @return void
	 */
	public static function reset($conn_name = '')
	{
		self::$instance->hide_all();

		for($i=self::$instance->get_n_pages(); $i >= 0; $i--)
		{
			self::$instance->remove_page($i);
		}

		if ( ! empty($conn_name))
		{
			unset(self::$instance->data->{$conn_name});
		}

		self::$instance->show_all();
	}

	// --------------------------------------------------------------------------

	/**
	 * Simplify adding tabs to the Notebook object
	 *
	 * @param object $conn
	 * @param string $tab_name
	 * @param string $col_name
	 * @param string $method
	 * @param array $events
	 * @return void
	 */
	private static function _add_tab(&$conn, $tab_name, $col_name, $method, $events=array())
	{
		$tab = new Data_Grid(new GTKTreeStore(Gobject::TYPE_PHP_VALUE));
		$tab_model = $tab->get_model();

		$conn_name = $conn->conn_name;

		$instance_data = self::$instance->_get_db_info($conn_name, $tab_name);

		$tab_data =  ($instance_data === FALSE)
			? call_user_func_array(array($conn, $method), array())
			: $instance_data;

		self::$instance->_set_db_info($conn_name, $tab_name, $tab_data);

		if ($tab_data !== FALSE)
		{
			foreach($tab_data as $d)
			{
				$tab_model->append(null, array($d));
			}

			$cell_renderer = new GtkCellRendererText();
			$cell_renderer->set_property('editable', FALSE);
			$tab->insert_column_with_data_func(0, $col_name, $cell_renderer, array($tab, 'add_data_col'));

			if ( ! empty($events))
			{
				foreach($events as $method)
				{
					call_user_func_array(array($tab, 'connect'), $method);
				}
			}

			self::$instance->add_tab($tab_name, $tab);

		}

		self::$instance->show_all();

		return;
	}

	// --------------------------------------------------------------------------

	/**
	 * Add a multidimensional array to a tab
	 *
	 * @param object $conn
	 * @param string $tab_name
	 * @param string $method
	 * @return void
	 */
	private static function _add_row_tab(&$conn, $tab_name, $method)
	{

		$conn_name = $conn->conn_name;

		$instance_data = self::$instance->_get_db_info($conn_name, $tab_name);

		$tab_data =  ($instance_data === FALSE)
			? call_user_func_array(array($conn, $method), array())
			: $instance_data;

		self::$instance->_set_db_info($conn_name, $tab_name, $tab_data);

		if ( ! empty($tab_data))
		{
			$tab = new Data_Grid();
			$tab->render_data($tab_data);

			self::$instance->add_tab($tab_name, $tab);
		}

		self::$instance->show_all();

		return;
	}

	// --------------------------------------------------------------------------

	/**
	 * Returns cached database data for the tab and connection specified
	 *
	 * @param type $conn_name
	 * @param type $tab_name
	 * @return mixed
	 */
	private function _get_db_info($conn_name, $tab_name)
	{
		$data =& self::$instance->data;

		if ( ! isset($data->{$conn_name}))
		{
			$data->{$conn_name}= array();
			return FALSE;
		}

		if ( ! isset($data->{$conn_name}[$tab_name]))
		{
			return FALSE;
		}

		return $data->{$conn_name}[$tab_name];
	}

	// --------------------------------------------------------------------------

	/**
	 * Sets cached database data for the tab and connection specified
	 *
	 * @param type $conn_name
	 * @param type $tab_name
	 * @param type $data
	 */
	private function _set_db_info($conn_name, $tab_name, $data)
	{
		self::$instance->data->{$conn_name}[$tab_name] = $data;
	}
}
// End of db_tabs.php