<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * TSM database connection using DSMADMC.
 *
 * @package    TSM Database Module
 * @category   Drivers
 * @author     Deon George
 * @copyright  (c) 2010-2014 Deon George
 * @license    http://dev.leenooks.net/license.html
 */
abstract class lnApp_Database_Tsm_dsmadmc extends Database_TSM {
	public function connect() {
		// Extract the connection parameters, adding required variabels
		extract($this->_config['connection'] + array(
			'database'   => '',
			'hostname'   => '',
			'username'   => '',
			'password'   => '',
			'persistent' => FALSE,
		));

		// Get user login details from user session - these are set by login
		if (! $username)
			$username = Session::instance()->get_once(Kohana::$config->load('auth')->session_key);
		if (! $password)
			$password = Session::instance()->get_once('password');

		// Prevent this information from showing up in traces
		unset($this->_config['connection']['username'], $this->_config['connection']['password']);

		if (! file_exists(Kohana::$config->load('tsm')->client)) {
			SystemMessage::TSM('error',sprintf('Unable to find the dsmadmc at <b>%s</b>',Kohana::$config->load('tsm')->client),'');

			return FALSE;
		}

		if (! $username OR ! $password)
			HTTP::redirect('login');

		try {
			if ($persistent) {
				// Create a persistent connection
				throw new Kohana_Exception('Cant do persistant connections');

			} else {
				// Create a connection and force it to be a new link
				$this->_connection = sprintf('%s %s -id=%s -password=%s -displ=list -editor=no -dataonly=YES %s %s ',
					Kohana::$config->load('tsm')->client,
					$database ? '-server='.$database : '',
					$username,
					$password,
					Kohana::$config->load('tsm')->client_errorlogname ? sprintf('-errorlogname=%s',Kohana::$config->load('tsm')->client_errorlogname) : '',
					$database ? sprintf('-se=%s',$database) : ''
				);

				$result = $this->query(Database::SELECT,'SELECT server_name,platform,version,release,level,sublevel FROM status');

				if ($result->count()) {
					return TSM::instance()->set($username,$password,$result);

				} else {
					$this->_connection = FALSE;

					// @todo Get ANS8034E (ID not recognised), or ??????E (invalid password)
					SystemMessage::add(array(
						'title'=>_('Login Failed'),
						'type'=>'error',
						'body'=>_('Invalid Username and/or Password.')
					));

					return FALSE;
				}
			}

		} catch (ErrorException $e) {
			// No connection exists
			$this->_connection = NULL;

			throw new Database_Exception(':error', array(
					':error' => sprintf('%s error in %s (%s)',$e->getMessage(),$e->getFile(),$e->getLine()),
				),
				$e->getCode());
		}
	}

	protected function execute($sql) {
		$this->execute_stdout = '';

		// We need to escape any back slashes, since the exec will transpose them
		// @todo Is there a better way of doing this?
		$sql = str_replace('\\','\\\\',$sql);

		$this->execute_stderr = exec($this->_connection.'"'.$sql.'"',$this->execute_stdout,$this->execute_rc);
		if (Kohana::$config->load('config.site.mode') == Kohana::DEVELOPMENT)
			SystemMessage::TSM('info',sprintf('%s (%s) [%s]',$this->_connection.'"'.$sql.'"',join("\n",$this->execute_stdout),$this->execute_rc),$sql);

		// Work out our message codes
		$result = array();
		foreach ($this->execute_stdout as $line)
			if (! preg_match('/^('.$this->msg_format.')\s+/',$line,$matches))
				array_push($result,$line);
			elseif (! in_array($matches[1],$this->ignore_codes))
				array_push($this->_query_msg_codes,$matches[1]);

		// If we got a no data code
		if (array_intersect($this->_query_msg_codes,$this->nodata_codes)) {
			$result = array();
			$this->execute_rc = 0;
		}

		return $result;
	}

	public function list_columns($table, $like = NULL, $add_prefix = TRUE) {
		// Quote the table name
		$table = ($add_prefix === TRUE) ? $this->quote_table($table) : $table;

		if (is_string($like))
			// Search for column names
			throw new Kohana_Exception('Like queries not implemented');
		else
			// Find all column names
			$result = $this->query(Database::SELECT, sprintf('SELECT * FROM SYSCAT.COLUMNS WHERE TABNAME=\'%s\'',$table), FALSE);

		$count = 0;
		$columns = array();
		foreach ($result as $row) {
			list($type, $length) = $this->_parse_type($row['TYPENAME']);

			$column = $this->datatype($type);

			$column['column_name']      = $row['COLNAME'];
			$column['data_type']        = $type;
			$column['is_nullable']      = ($row['NULLS'] == 'TRUE');
			$column['ordinal_position'] = ++$count;

			switch (strtolower($column['data_type'])) {
				case 'float':
					if (isset($length))
						list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
					break;

				case 'int':
					if (isset($length))
						// MySQL attribute
						$column['display'] = $length;
					break;

				case 'string':
					switch ($column['data_type']) {
						case 'binary':
						case 'varbinary':
							$column['character_maximum_length'] = $length;
							break;

						case 'char':
						case 'varchar':
							$column['character_maximum_length'] = $length;
						case 'text':
						case 'tinytext':
						case 'mediumtext':
						case 'longtext':
							$column['collation_name'] = $row['Collation'];
							break;

						case 'enum':
						case 'set':
							$column['collation_name'] = $row['Collation'];
							$column['options'] = explode('\',\'', substr($length, 1, -1));
							break;
					}

					break;
			}

			// TSM attributes
			$column['comment']        = $row['REMARKS'];
			$columns[$row['COLNAME']] = $column;
		}

		return $columns ? $columns : array('');
	}
}
?>