/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.empire.db;

import java.sql.Connection;

import org.apache.empire.commons.Attributes;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.OptionEntry;
import org.apache.empire.commons.Options;
import org.apache.empire.data.Column;
import org.apache.empire.data.DataType;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.InvalidPropertyException;
import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.exceptions.PropertyReadOnlyException;
import org.apache.empire.xml.XMLUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;


/**
 * This class represent one column of a table.
 * It contains all properties of this columns (e.g. the column width).
 * 
 *
 */
public class DBTableColumn extends DBColumn
{
    // *Deprecated* private static final long serialVersionUID = 1L;
    private static final Logger log = LoggerFactory.getLogger(DBTableColumn.class);
    
    // Column Information
    protected DataType  type;
    protected double    size;
    protected boolean   required;
    protected boolean   autoGenerated;
    protected boolean   readOnly;
    protected Object    defaultValue;
    protected int 		decimalScale = 0;

    /**
     * Constructs a DBTableColumn object set the specified parameters to this object.
     * 
     * @param table the table object to add the column to, set to null if you don't want it added to a table
     * @param type the type of the column e.g. integer, text, date
     * @param name the column name
     * @param size the column width
     * @param dataMode determines whether this column is optional, required or auto-generated 
     * @param defValue the object value
     */
    public DBTableColumn(DBTable table, DataType type, String name, double size, boolean required, boolean autoGenerated, Object defValue)
    {
        super(table, name);
        // check properties
        // set column properties
        this.type = type;
        this.required = required;
        this.autoGenerated = autoGenerated;
        this.readOnly = autoGenerated;
        this.defaultValue = defValue;
        // xml
        this.attributes = new Attributes();
        this.options = null;
        // size (after attributes!)
        setSize(size);
    }
    
    /**
     * Clone Constructor - use clone()
     */
    protected DBTableColumn(DBTable newTable, DBTableColumn other)
    {
        super(newTable, other.name);
        // Copy
        this.type = other.type;
        this.size = other.size;
        this.required = other.required;
        this.autoGenerated = other.autoGenerated;
        this.readOnly = other.readOnly;
        this.defaultValue = other.defaultValue;
        this.attributes = new Attributes();
        this.attributes.addAll(other.attributes);
        this.options = other.options;
        if (newTable != null)
        {
            newTable.addColumn(this);
        }
    }
    
    /**
     * Returns the default column value.
     * For columns of type DBDataType.AUTOINC this is assumed to be the name of a sequence
     * 
     * @return the default column value
     */
    public Object getDefaultValue()
    {
        return defaultValue;
    }

    /**
     * Sets the default column value.
     * 
     * @param defValue the default column value
     */
    public void setDefaultValue(Object defValue)
    {
        this.defaultValue = defValue;
    }
    
    /**
     * Returns the default column value. 
     * Unlike getDefaultValue this function is used when creating or adding records.
     * If the column value is DBDataType AUTOIN this function will return a new sequence value for this record
     * 
     * @param conn a valid database connection
     * @return the default column value
     */
    public Object getRecordDefaultValue(Connection conn)
    {	// Check params   
        if (rowset==null)
            return defaultValue;
        // Detect default value
        if (isAutoGenerated())
        {   // If no connection is supplied defer till later
        	if (conn==null)
        		return null; // Create Later
            // Other auto-generated values
	        DBDatabase db = rowset.getDatabase();
            return db.getDbms().getColumnAutoValue(db, this, conn);
        }
        // Normal value
        return defaultValue;
    }

    /**
     * Returns the data type.
     * 
     * @return the data type
     */
    @Override
    public DataType getDataType()
    {
        return type;
    }

    /**
     * Gets the the column width.
     * 
     * @return the column width
     */
    @Override
    public double getSize()
    {
        return size;
    }

    /**
     * Changes the size of the table column<BR>
     * Use for dynamic data model changes only.<BR>
     * @param size the new column size
     */
    public void setSize(double size)
    {
        // Negative size?
        if (size<0)
        {   // For Text-Columns set attribute "SINGLEBYTECHARS"
            if (getDataType().isText())
            {
                setAttribute(DBCOLATTR_SINGLEBYTECHARS, Boolean.TRUE);
            }    
            else
                throw new InvalidArgumentException("size", size);
            // Remove sign
            size = Math.abs(size);
        }
        else if (attributes!=null && attributes.contains(DBCOLATTR_SINGLEBYTECHARS))
        {   // Remove single by chars attribute
            attributes.remove(DBCOLATTR_SINGLEBYTECHARS);
        }
        // set now
        this.size = size;
        // set scale
    	if (getDataType()==DataType.DECIMAL)
    	{	// set scale from size
		    int reqPrec = (int)size;
		    this.decimalScale = ((int)(size*10)-(reqPrec*10));
    	}
    }
    
    /**
     * Returns the scale of the Decimal or 0 if the DataType is not DataType.DECIMAL.
     * @return the decimal scale
     */
    public int getDecimalScale()
    {
	    return this.decimalScale;
    }
    
    /**
     * Sets the scale of a decimal. The DataType must be set to DataType.DECIMAL otherwise an exception is thrown. 
     */
    public void setDecimalScale(int scale)
    {
    	if (getDataType()!=DataType.DECIMAL)
    		throw new NotSupportedException(this, "setDecimalScale");
    	// return scale
	    this.decimalScale = scale;
    }

    /**
     * Returns true if column is mandatory. Only for the graphic presentation.
     * 
     * @return true if column is mandatory 
     */
    @Override
    public boolean isRequired()
    {
        return this.required;
    }
    
    /**
     * Returns true if column is a numeric sequence or otherwise generated value
     * 
     * @return true if column is auto increment
     */
    @Override
    public boolean isAutoGenerated()
    {
        return this.autoGenerated;
    }
    
    /**
     * Returns true if column the column is a single byte text or character column or false otherwise
     * 
     * @return true if column is a single byte character based column
     */
    public boolean isSingleByteChars()
    {
        if (attributes==null || !attributes.contains(DBCOLATTR_SINGLEBYTECHARS))
            return false;
        // Check Attribute
        return ObjectUtils.getBoolean(attributes.get(DBCOLATTR_SINGLEBYTECHARS));
    }
    
    /**
     * sets whether this column is a single byte character or text column 
     */
    public void setSingleByteChars(boolean singleByteChars)
    {
        if (!getDataType().isText())
            throw new NotSupportedException(this, "setSingleByteChars");
        // set single byte
        setAttribute(DBCOLATTR_SINGLEBYTECHARS, singleByteChars);
    }

    /**
     * Changes the required property of the table column<BR>
     * Use for dynamic data model changes only.<BR>
     * @param required true if the column is required or false otherwise
     */
    public void setRequired(boolean required)
    {
        if (isAutoGenerated())
        {	// cannot change auto-generated columns
            throw new PropertyReadOnlyException("required"); 
        }
        else
        {	// Set DataMode
        	this.required = required;
        }
    }

    /**
     * Checks whether the column is read only.
     * 
     * @return true if the column is read only
     */
    @Override
    public boolean isReadOnly()
    {   
        return this.readOnly;
    }

    /**
     * Sets the read only attribute of the column.
     *
     * @param readOnly true if the column should be read only or false otherwise
     */
    public void setReadOnly(boolean readOnly)
    {
        this.readOnly = readOnly;
    }
    
    /**
     * sets the options from an enum class
     */
    public void setEnumOptions(Class<?> enumType)
    {
        // Enum special treatment
        log.debug("Adding enum options of type {} for column {}.", enumType.getName(), getName());            
        this.options = new Options(enumType);
        // set enumType
        setAttribute(Column.COLATTR_ENUMTYPE, enumType);
        // check length
        if (getDataType().isNumeric())
            return; // no check required
        int maxLength = (int)size;
        for (OptionEntry oe : options)
        {   // check length
            String val = oe.getValueString();
            if (val!=null && val.length()>maxLength)
                throw new InvalidPropertyException(enumType.getName(), val);
        }
    }

    /**
     * Checks whether the supplied value is valid for this column.
     * If the type of the value supplied does not match the columns
     * data type the value will be checked for compatibility. 
     * 
     * @param value the checked to check for validity
     * @return true if the value is valid or false otherwise.
     */
    @Override
    public Object validateValue(Object value)
    {
        return ((DBTable)rowset).validateValue(this, value);
    }

    /**
     * Creates a foreign key relation for this column.
     * 
     * @param target the referenced primary key column
     * @return the reference object
     */
    public DBRelation.DBReference referenceOn(DBTableColumn target)
    {
        return new DBRelation.DBReference(this, target);
    }

    /**
     * Sets field elements, default attributes and all options to
     * the specified Element object (XML tag).
     * 
     * @param parent the parent object
     * @param flags a long value
     * @return the work up Element object
     */
    @Override
    public Element addXml(Element parent, long flags)
    { // Add Field element
        Element elem = XMLUtil.addElement(parent, "column");
        elem.setAttribute("name", name);
        // set default attributes
        DBIndex primaryKey = ((DBTable) rowset).getPrimaryKey();
        if (primaryKey != null)
        {
            int keyIndex;
            if ((keyIndex = ((DBTable) rowset).getPrimaryKey().getColumnPos(this)) >= 0)
                elem.setAttribute("key", String.valueOf(keyIndex + 1));
        }
        if (size > 0)
        {
            elem.setAttribute("size", String.valueOf((int)size));
            if (getDataType()==DataType.DECIMAL)
                elem.setAttribute("decimals", String.valueOf((int)(size*10)%10));
        }
        if (isRequired())
            elem.setAttribute("mandatory", String.valueOf(Boolean.TRUE));
        // add All Attributes
        if (attributes!=null)
            attributes.addXml(elem, flags);
        // add All Options
        if (options!=null)
            options.addXml(elem, this.type);
        // done
        return elem;
    }
}