<?php

class MCustomField26
{
    /**
     * Constants for field formats.
     */
    const FORMAT_TEXT = 'text';
    const FORMAT_LONG_TEXT = 'longText';
    const FORMAT_INTEGER = 'integer';
    const FORMAT_DECIMAL = 'decimal';
    const FORMAT_LIST = 'list';
    const FORMAT_LISTSQL = 'listsql';
    const FORMAT_DATE = 'date';
    const FORMAT_BOOLEAN = 'boolean';
    const FORMAT_HIDDEN = 'oculto';

    /**
     * @var integer Unique id used as input id together with the identifier.
     */
    public $id;

    /**
     * @var string The identifier of the field, usually a table or form name.
     */
    public $identifier;

    /**
     * @var string Name of the field.
     */
    public $name;
    
    /**
     * Label of the field.
     *
     * @var string
     */
    public $label;

    /**
     * @var string Field format. Use the FORMAT_* constants to set it.
     */
    public $fieldFormat;

    /**
     * @var string List of possible values separated by \n.
     */
    public $possibleValues;

    /**
     * @var string Regular expression. 
     */
    public $regexp;

    /**
     * @var integer Minimum length.
     */
    public $minLength;

    /**
     * @var integer Maximum length.
     */
    public $maxLength;

    /**
     * @var character Whether field is required ('t' or 'f').
     */
    public $required;

    /**
     * @var integer Position of the field to be ordered.
     */
    public $position;

    /**
     * @var string Default value.
     */
    public $defaultValue;

    /**
     * @var character Whether field is editable ('t' or 'f').
     */
    public $editable;

    /**
     * @var character Whether field is visible ('t' or 'f').
     */
    public $visible;

    /**
     * @var string Input id suffix.
     */
    public $suffix;
    
    /**
     * @var string
     */
    public $possibleParameters;

    /**
     * @var string
     */
    public $paramNotFound;
    
    /**
     * @var boolean
     */
    public $filtroFormularioBusca;
    
    /**
     * MCustomField constructor.
     *
     * @param object $data A stdClass instance to populate this object.
     */
    public function __construct($data=NULL)
    {
        if ( $data )
        {
            $this->setData($data);
        }
    }

    /**
     * @return object MBusiness instance.
     */
    private static function getBusiness()
    {
        $MIOLO = MIOLO::getInstance();
        return new MBusiness('base');
    }

    /**
     * @return string Get the id to use on inputs.
     */
    public function getInputId()
    {
        return self::generateInputId($this->identifier, $this->id, $this->suffix);
    }

    /**
     * Generate the id to use on inputs.
     *
     * @param string $identifier The identifier of the field, usually a table or form name.
     * @param string $id Unique custom field id.
     * @param string $suffix Suffix to be added to each field name.
     * @return string Input id.
     */
    public static function generateInputId($identifier, $id, $suffix='')
    {
        return "{$identifier}_$id$suffix";
    }

    /**
     * Set the object attributes.
     *
     * @param object $data A stdClass instance.
     */
    public function setData($data)
    {
        $this->id = $data->id;
        $this->identifier = $data->identifier;
        $this->name = $data->name;
        $this->fieldFormat = $data->fieldFormat;
        $this->possibleValues = $data->possibleValues;
        $this->regexp = $data->regexp;
        $this->minLength = $data->minLength;
        $this->maxLength = $data->maxLength;
        $this->required = $data->required;
        $this->position = $data->position;
        $this->defaultValue = $data->defaultValue;
        $this->editable = $data->editable;
        $this->visible = $data->visible;
        $this->filtroFormularioBusca = $data->filtroFormularioBusca;
        $this->visivel = $data->visivel;
    }

    /**
     * Insert a custom field.
     *
     * @return object Result of the insertion.
     */
    public function insert()
    {
        $this->id = $this->getBusiness()->_db->getNewId('miolo_custom_field_id_seq', 'miolo_sequence');

        $sql = new MSQL(
            'id, identifier, name, field_format, possible_values, regexp, min_length, max_length, required, position, default_value, editable, visible, filtroFormularioBusca, visivel',
            'miolo_custom_field'
        );

        $args = array(
            $this->id,
            $this->identifier,
            $this->name,
            $this->fieldFormat,
            $this->possibleValues,
            $this->regexp,
            $this->minLength,
            $this->maxLength,
            $this->required,
            $this->position,
            $this->defaultValue,
            $this->editable,
            $this->visible,
            $this->filtroFormularioBusca,
            $this->visivel
        );

        return self::getBusiness()->execute($sql->insert($args));
    }

    /**
     * Update a custom field.
     *
     * @return object Result of the update.
     */
    public function update()
    {
        $sql = new MSQL(
            'identifier, name, field_format, possible_values, regexp, min_length, max_length, required, position, default_value, editable, visible, filtroFormularioBusca, visivel',
            'miolo_custom_field',
            'id = ?'
        );

        $args = array(
            $this->identifier,
            $this->name,
            $this->fieldFormat,
            $this->possibleValues,
            $this->regexp,
            $this->minLength,
            $this->maxLength,
            $this->required,
            $this->position,
            $this->defaultValue,
            $this->editable,
            $this->visible,
            $this->filtroFormularioBusca,
            $this->visivel,
            $this->id,
        );

        return self::getBusiness()->execute($sql->update($args));
    }

    /**
     * Delete a custom field.
     *
     * @return object Result of the removal.
     */
    public function delete()
    {
        if ( !isset($this->id) )
        {
            return false;
        }

        $sql = new MSQL('', 'miolo_custom_field', 'id = ?');
        return self::getBusiness()->execute($sql->delete($this->id));
    }

    /**
     * Populate the object querying the database by the id.
     */
    public function populate()
    {
        $sql = new MSQL(
            'identifier, name, label, field_format, possible_values, regexp, min_length, max_length, required, position, default_value, editable, visible, possible_parameters, filtroFormularioBusca, visivel',
            'miolo_custom_field',
            'id = ?'
        );

        $query = self::getBusiness()->query($sql, $this->id);

        list(
            $this->identifier,
            $this->name,
            $this->label,
            $this->fieldFormat,
            $this->possibleValues,
            $this->regexp,
            $this->minLength,
            $this->maxLength,
            $this->required,
            $this->position,
            $this->defaultValue,
            $this->editable,
            $this->visible,
            $this->possibleParameters,
            $this->filtroFormularioBusca,
            $this->visivel
        ) = $query->result[0];
    }

    /**
     * @return boolean Whether the required attribute has the database true value.
     */
    public function isRequired()
    {
        return $this->required == 't';
    }

    /**
     * @return boolean Whether the editable attribute has the database true value.
     */
    public function isEditable()
    {
        return $this->editable == 't';
    }

    /**
     * @return boolean Whether the visible attribute has the database true value.
     */
    public function isVisible()
    {
        return $this->visible == 't';
    }

    /**
     * List the custom fields with the given identifier.
     *
     * @param string $identifier The identifier of the field, usually a table or form name.
     * @return array Array of MCustomField instances.
     */
    public static function listByIdentifier($identifier)
    {
        $sql = new MSQL(
            'id, identifier, name, label, field_format, possible_values, regexp, min_length, max_length, required, position, default_value, editable, visible, possible_parameters, filtroFormularioBusca, visivel',
            'miolo_custom_field',
            'identifier = ?',
            'position, name'
        );

        $query = self::getBusiness()->query($sql, $identifier);

        $list = array();

        if ( $query->result )
        {
            foreach ( $query->result as $row )
            {
                $cf = new self();

                list(
                    $cf->id,
                    $cf->identifier,
                    $cf->name,
                    $cf->label,
                    $cf->fieldFormat,
                    $cf->possibleValues,
                    $cf->regexp,
                    $cf->minLength,
                    $cf->maxLength,
                    $cf->required,
                    $cf->position,
                    $cf->defaultValue,
                    $cf->editable,
                    $cf->visible,
                    $cf->possibleParameters,
                    $cf->filtroFormularioBusca,
                    $cf->visivel
                ) = $row;

                $list[] = $cf;
            }
        }

        return $list;
    }

    /**
     * List the custom fields to show them on a grid.
     *
     * @param string $identifier The identifier of the field, usually a table or form name.
     * @return array Matrix of strings with the custom fields data.
     */
    public static function listForGrid($identifier='')
    {
        $MIOLO = MIOLO::getInstance();

        $where = $identifier ? 'identifier = ?' : '';

        $sql = new MSQL(
            'id,
             identifier,
             name,
             field_format,
             possible_values,
             required,
             filtroFormularioBusca ',
            'miolo_custom_field',
            $where,
            'identifier, position, name'
        );

        $query = self::getBusiness()->query($sql, $identifier);

        return $query->result;
    }

    /**
     * @return array List the possible format fields to use on formatField attribute.
     */
    public static function listFormatFields()
    {
        return array(
            self::FORMAT_TEXT => _M('Text'),
            self::FORMAT_LONG_TEXT => _M('Long text'),
            self::FORMAT_INTEGER => _M('Integer'),
            self::FORMAT_DECIMAL => _M('Decimal'),
            self::FORMAT_LIST => _M('List'),
            self::FORMAT_LISTSQL => _M('Lista (SQL)'),
            self::FORMAT_DATE => _M('Date'),
            self::FORMAT_BOOLEAN => _M('Boolean'),
        );
    }

    /**
     * Method created to allow the aliases sId, sName and sVisible for id, name and visible.
     * This is to avoid problems with subdetail.
     *
     * @param string $attr Attribute name.
     * @return mixed Value.
     */
    public function __get($attr)
    {
        if ( $attr == 'sId' ) return $this->id;
        if ( $attr == 'sName' ) return $this->name;
        if ( $attr == 'sVisible' ) return $this->visible;
    }
    
    /**
     * @return boolean
     */
    public function hasSQLParameters()
    {
        return substr_count($this->possibleValues, '?') > 0;
    }
    
    /**
     * Obtem um array com parametros possiveis
     * 
     * @return array
     */
    public function parsePossibleParameters()
    {
        return (array) explode(',', $this->possibleParameters);
    }
    
    /**
     * @return array
     */
    public function getParameterArgs()
    {
        $MIOLO = MIOLO::getInstance();
        $args = array();

        foreach ( $this->parsePossibleParameters() as $parameter )
        {
            // Tenta buscar valor do REQUEST
            $requestValue = MIOLO::_REQUEST($parameter);

            // Se nao encontrar valor, busca do $_REQUEST ignorando maiusculas/minusculas
            if ( strlen($requestValue) == 0 )
            {
                $data = array_change_key_case($_REQUEST, CASE_LOWER);

                $requestValue = $data[strtolower($parameter)];
            }
            
            // Se nao encontrar valor, tenta buscar de dados de passo a passo
            if ( strlen($requestValue) == 0 )
            {
                $isFromSAGU = $MIOLO->getConf('temp.is.from.sagu');
                
                if ( $isFromSAGU )
                {
                    $data = (array) sstepbystepform::getAllStepDataStatic();
                    $data = array_change_key_case($data, CASE_LOWER);
                    
                    $requestValue = $data[strtolower($parameter)];
                }
            }
            
            if ( strlen($requestValue) == 0 && strlen($this->paramNotFound) == 0 )
            {
                $this->paramNotFound = $parameter;
            }

            $args[] = $requestValue;
        }
        
        return $args;
    }
    
    /**
     * Substitui os coringas (?) de parametros do SQL, caso necessario
     * 
     * @return string
     */
    public function replaceSQLParameters($sql)
    {
        if ( $this->hasSQLParameters() )
        {
            $MIOLO = MIOLO::getInstance();
            $isFromSAGU = $MIOLO->getConf('temp.is.from.sagu');
            
            if ( $isFromSAGU )
            {
                $args = $this->getParameterArgs();
                
                // executa o comando de substituicao dos coringas
                $sql = SAGU::prepare($sql, $args, false);
            }
        }
        
        return $sql;
    }
    
    /**
     *
     * @return array
     */
    public function getListSQL()
    {
        $MIOLO = MIOLO::getInstance();
        $list = array();
        
        if ( strlen($this->possibleValues) > 0 && ( $this->fieldFormat == MCustomField26::FORMAT_LISTSQL ) )
        {
            $db = $MIOLO->GetDatabase('base');
            $query = $db->Query($this->replaceSQLParameters($this->possibleValues));
            
            foreach ( (array) $query as $row )
            {
                $list[ $row[0] ] = $row[1];
            }
        }
        
        return $list;
    }
    
    public function getFieldHint()
    {
        if ( $this->hasSQLParameters() && strlen($this->paramNotFound) > 0 )
        {
            return _M("Não foi encontrado valor para o parâmetro '@1' configurado.", null, $this->paramNotFound);
        }
    }
    
    /**
     * @return array 
     */
    public function getListValues()
    {
        $possibleValues = explode("\n", trim($this->possibleValues));
        $list = array();

        foreach ( $possibleValues as $val )
        {
            $value = trim($val);
            $list[$value] = $value;
        }
        
        return $list;
    }
}
?>
