<?php

/**
 * Goweb Sitemanager 5 Framework
 * 
 * @version    5.0.0
 * @category   Goweb
 * @package    Goweb_Db
 * @subpackage Model
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */

/**
 * Goweb_Db_Model_Adapter_Interface
 */
Goweb::loadClass('Goweb_Db_Model_Adapter_Interface');

/**
 * Classe que implementa o interface Goweb_Db_Model_Adapter_Interface
 * para a base de dados do tipo Mysql.
 *
 * @version    5.0.0
 * @category   Goweb
 * @package    Goweb_Db
 * @subpackage Model
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */
class Goweb_Db_Model_Adapter_Mysql implements Goweb_Db_Model_Adapter_Interface {

    protected $_reverseTypes = array('VARCHAR'    => 'Char',
                                     'TINYINT'    => 'Char',
                                     'TEXT'       => 'Text',
                                     'DATE'       => 'Date',
                                     'SMALLINT'   => 'SmallInteger',
                                     'MEDIUMINT'  => 'Integer',
                                     'INT'        => 'Integer',
                                     'BIGINT'     => 'Integer',
                                     'FLOAT'      => 'Float',
                                     'DOUBLE'     => 'Float',
                                     'DECIMAL'    => 'Float',
                                     'DATETIME'   => 'Datetime',
                                     'TIMESTAMP'  => 'Datetime',
                                     'TIME'       => 'Time',
                                     'YEAR'       => 'Date',
                                     'CHAR'       => 'Char',
                                     'TINYBLOB'   => 'Blob',
                                     'TINYTEXT'   => 'Text',
                                     'BLOB'       => 'Blob',
                                     'MEDIUMBLOB' => 'Blob',
                                     'MEDIUMTEXT' => 'Text',
                                     'LONGBLOB'   => 'Blob',
                                     'LONGTEXT'   => 'Text',
                                     'ENUM'       => 'Char',
                                     'SET'        => 'Char',
                                     'BOOL'       => 'Boolean',
                                     'BINARY'     => 'SmallInteger',
                                     'VARBINARY'  => 'SmallInteger');
    
    /**
     * Retorna o array com o mapeamento do tipo de coluna => Goweb_Db_Model_Col.
     * 
     * @return  array  o mapeamento do tipo de coluna => Goweb_Db_Model_Col
     */
    public function getReverseTypes() {
        return $this->_reverseTypes;
    }

    /**
     * Retorna o SQL respeitante e remocao de uma tabela.
     *
     * @param   bool    $ifExists  Adiciona o IF EXISTS se for TRUE
     * @return  string             String SQL
     */
    public function getDropTable($ifExists = false) {
        return 'DROP TABLE' . ($ifExists ? ' IF EXISTS' : '');
    }
    
    /**
     * Retorna o SQL respeitante e criacao de uma col.
     * 
     * @param   string           O nome da tabela
     * @return  string           String SQL
     */
    public function getAddCol($table) {
        return 'ALTER TABLE ' . $table . ' ADD';
    }

    /**
     * Retorna o SQL respeitante e remocao de uma col.
     *
     * @param   string           O nome da tabela
     * @return  string           String SQL
     */
    public function getDropCol($table) {
        return 'ALTER TABLE ' . $table . ' DROP';
    }

    /**
     * Retorna o SQL respeitante e alteracao de uma col.
     *
     * @param   string           O nome da tabela
     * @return  string           String SQL
     */
    public function getChangeCol($table) {
        return 'ALTER TABLE ' . $table . ' CHANGE';
    }

    /**
     * Retorna o SQL respeitante e alteracao de uma col mantendo o seu nome.
     *
     * @param   string           O nome da tabela
     * @return  string           String SQL
     */
    public function getModifyCol($table) {
        return 'ALTER TABLE ' . $table . ' MODIFY';
    }
    
    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Auto.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getAuto($params) {
        return 'integer unsigned AUTO_INCREMENT PRIMARY KEY';
    }
                                        
    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Boolean.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getBoolean($params) {
        $output  = 'boolean';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default ' . $params['default'] : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Char.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getChar($params) {
        if (isset($params['options']) && $params['options']){
            $output  = 'longtext';
        } else {
            $output  = 'varchar(' . $params['maxlength'] . ')';
        }
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        if (!isset($params['options']) || !$params['options']){
            $output .= $params['default'] !== null ? ' default \'' . $params['default'] . '\'' : '';
        }
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Text.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getText($params) {
        $output  = (array_key_exists('coltype', $params) && $params['coltype']) ? $params['coltype'] : 'longtext';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        if ((array_key_exists('coltype', $params) && $params['coltype'])){
            $output .= $params['default'] !== null ? ' default \'' . $params['default'] . '\'' : '';
        }
        return $output;
    }
    /**
     * Retorna o SQL respeitante e definicao de campos do tipo ColorPicker.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getColorPicker($params) {
        $output  = (array_key_exists('coltype', $params) && $params['coltype']) ? $params['coltype'] : 'longtext';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] . '\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Password.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getPassword($params) {
        $output  = 'varchar(' . $params['maxlength'] . ')';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default ' . $params['default'] : '';
        return $output;
    }
    
    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Blob.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
    */
    public function getBlob($params) {
        $output  = 'blob';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default '.$params['default'] : '';
        return $output;
    }
                                    
    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Date.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getDate($params) {
        $output  = 'date';
        $output .= ' NOT NULL';
        $output .= $params['default'] !== null ? ' default \'' . $params['default']  . '\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Datetime.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getDatetime($params) {
        $output  = 'datetime';
        $output .= ' NOT NULL';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] . '\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Time.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getTime($params) {
        $output  = 'time';
        $output .= ' NOT NULL';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] . '\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo File.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getFile($params) {
        $output  = 'varchar(' . $params['maxlength'] . ')';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] . '\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Filepath.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getFilepath($params) {
        $output  = 'varchar(' . $params['maxlength'] . ')';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] .'\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Float.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getFloat($params) {
        $output  = 'numeric(' . (intval($params['max_digits']) + intval($params['decimal_places'])) . ', ' . $params['decimal_places'] . ')';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default ' . $params['default'] : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Image.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getImage($params) {
        $output  = 'varchar(' . $params['maxlength'] . ')';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] . '\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Integer.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */    
    public function getInteger($params) {
        $output  = 'integer';
        $output .= $params['maxlength'] ? ('(' . $params['maxlength'] . ')')  : '';
        $output .= $params['unsigned'] ? ' unsigned' : '';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default ' . $params['default'] : '';
        $output .= $params['primary'] ? ' PRIMARY KEY' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo SmallInteger.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getSmallInteger($params) {
        $output  = 'smallint';
        $output .= $params['maxlength'] ? ('(' . $params['maxlength'] . ')')  : '';
        $output .= $params['unsigned'] ? ' unsigned' : '';        
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default ' . $params['default'] : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo IpAddress.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getIpAddress($params) {
        $output  = 'char(15)';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] .'\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Url.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getUrl($params) {
        $output  = 'varchar(255)';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] . '\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo Email.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getEmail($params) {
        $output  = 'varchar(200)';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        $output .= $params['default'] !== null ? ' default \'' . $params['default'] .'\'' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo ForeignKey.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getForeignKey($params) {
        $output  = 'integer unsigned';
        $output .= ' NOT NULL';
        $output .= $params['default'] !== null ? ' default ' . $params['default'] : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo ForeignKey.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getForeignKeyMultiple($params) {
        $output  = 'longtext';
        $output .= $params['notnull'] ? ' NOT NULL' : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao de campos do tipo SelectFill.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getSelectFill($params) {
        $output  = 'integer unsigned';
        $output .= ' NOT NULL';
        $output .= $params['default'] !== null ? ' default ' . $params['default'] : '';
        return $output;
    }
    
    /**
     * Retorna o SQL respeitante e definicao de campos do tipo SelfKey.
     * 
     * @param   array   $params  Paremetros de configuracao
     * @return  string           String SQL
     */
    public function getSelfKey($params) {
        $output  = 'integer unsigned';
        $output .= ' NOT NULL';
        $output .= $params['default'] !== null ? ' default ' . $params['default'] : '';
        return $output;
    }

    /**
     * Retorna o SQL respeitante e definicao do cabecalho da criacao de tabelas.
     * 
     * @param   string   $tableName  Nome da tabela
     * @return  string               String SQL
     */
    public function getCreateStart($tableName) {
        return 'CREATE TABLE ' . $tableName .' (';
    }

    /**
     * Retorna o SQL respeitante e definicao do rodape da criacao de tabelas.
     * 
     * @return  string               String SQL
     */    
    public function getCreateEnd() {
        return ');';
    }

    /**
     * Retorna a instrucao de criacao de indices.
     * 
     * @param   string  $index  Nome do indice
     * @param   string  $col    Nome da coluna
     * @param   string  $table  Nome da tabela
     * @return  string          String SQL  
     */
    public function getCreateIndex($index, $col, $table) {
        return 'CREATE INDEX ' . $index .' ON ' . $table .' (' . $col . ');';
    }
}
