/*******************************************************************************
 * Copyright (c) 2007, 2009 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.gen.internal;

import java.util.Collections;

import org.eclipse.jpt.db.Column;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.gen.internal.old.EntityGenTools;
import org.eclipse.jpt.gen.internal.util.StringUtil;


/**
 * Represents the ORM generation properties for a database 
 * column.
 * 
 * <p>This is designed to be created/changed by the generation wizard,
 * and generated using Velocity templates.
 * The modified properties (if any) are persisted/retrieved using 
 * <code>ORMGenCustomizer</code>.
 * 
 */
public class ORMGenColumn
{
	private Table mTable;
	private Column mDbColumn;
	private ORMGenCustomizer mCustomizer;
	private ORMGenTable mGenTable;
	private static String JAVA_LANG_PACKAGE = "java.lang."; //$NON-NLS-1$
	
	public ORMGenColumn(Column dbColumn, ORMGenCustomizer customizer) {
		super();
		
		mDbColumn = dbColumn;
		mCustomizer = customizer;
		mTable = dbColumn.getTable();
	}
	
	public ORMGenCustomizer getCustomizer() {
		return mCustomizer;
	}
	
	public void setGenTable(ORMGenTable ormGenTable) {
		mGenTable = ormGenTable;
	}
	
	protected String customized(String propName) {
		return getCustomizer().getProperty(propName, mTable.getName(), getName());
	}
	
	protected boolean customizedBoolean(String propName) {
		return getCustomizer().getBooleanProperty(propName, mTable.getName(), getName());
	}
	
	protected void setCustomized(String propName, String value) {
		if (value != null && value.length() == 0) {
			value = null;
		}
		getCustomizer().setProperty(propName, value, mTable.getName(), getName());
	}
	
	protected void setCustomizedBoolean(String propName, boolean value, boolean defaultValue) {
		if (defaultValue == value) {
			setCustomized(propName, null); //remove the property
		} else {
			getCustomizer().setBooleanProperty(propName, value, mTable.getName(), getName());
		}
	}
	
	/**
	 * Returns the column name.
	 */
	public String getName() {
		String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
			buildColumnAnnotationName(mDbColumn.getName(), mDbColumn);
		return annotationName != null ? annotationName : mDbColumn.getName();
	}

	public String getJoinColumnName(){
		String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
			buildJoinColumnAnnotationName(mDbColumn);
		return annotationName != null ? annotationName : mDbColumn.getName();
	}
	
	public Column getDbColumn() {
		return this.mDbColumn;
	}
	
	/**
	 * Returns the generated bean property name for the given column.
	 * Does not return null.
	 */
	public String getPropertyName() {
		String name = customized(PROPERTY_NAME);
		if (name == null) {
			//name = StringUtil.columnNameToVarName(getName());
			name = EntityGenTools.convertToUniqueJavaStyleAttributeName(getName(), Collections.<String>emptySet());
		}
		return name;
	}
	
	public void setPropertyName(String name) {
		if (!StringUtil.equalObjects(name, getPropertyName())) {
			setCustomized(PROPERTY_NAME, name);
		}
	}
	
	/**
	 * Return true if the values of name element in the @Column is default
	 * so we can skip generating the annotation
	 * 
	 * @return true
	 */
	public boolean isDefault(){
		return isDefaultname() && isUpdateable() && isInsertable();
	}
	
	/**
	 * Return true if the values of name element in the @Column is default
	 * so we can skip generating the annotation
	 * 
	 * @return true
	 */
	public boolean isDefaultname(){
		String propName = getPropertyName();
//		String dbColumnName = getName();
//		return propName.equalsIgnoreCase( dbColumnName );
		String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
			buildColumnAnnotationName(propName, this.mDbColumn );
		return annotationName==null;
	}

	
	/**
	 * Returns the column type.
	 * Does not return null.
	 */
	public String getPropertyType()  {
		String type = customized(PROPERTY_TYPE);
		if (type == null) {
			type = getCustomizer().getPropertyTypeFromColumn( this.mDbColumn );
		}
		if( type.startsWith(JAVA_LANG_PACKAGE) ) {
			type = type.substring( JAVA_LANG_PACKAGE.length() );
		}
		if( type.equals("java.sql.Date")){ //$NON-NLS-1$
			type = "java.util.Date"; //$NON-NLS-1$
		}
			
		return type;
	}
	
	public String getSimplePropertyType()  {
		return mGenTable.getSimplifiedColType( getPropertyType() );
	}	
	
	public void setPropertyType(String type)  {
		if (!StringUtil.equalObjects(type, getPropertyType())) {
			setCustomized(PROPERTY_TYPE, type);
		}
	}
	/**
	 * Returns true if the column type is numeric.
	 */
	public boolean isNumeric() {
		boolean ret = this.mDbColumn.isNumeric();
		return ret;
	}
	
	/**
	 * Returns the mapping kind, one of {@link #PROPERTY_MAPPING_KIND}|{@link #ID_MAPPING_KIND}
	 * |{@link #VERSION_MAPPING_KIND}|{@link #TIMESTAMP_MAPPING_KIND}.
	 * 
	 * This method does not return null (defaults to basic property type).
	 */
	public String getMappingKind() {
		String kind = customized(MAPPING_KIND);
		if (kind == null) {
			kind = getCustomizer().getBasicMappingKind();
			
			if ( this.mDbColumn.isPartOfPrimaryKey() 
				 && this.mDbColumn.getTable().getPrimaryKeyColumnsSize() == 1) {
				kind = getCustomizer().getIdMappingKind();
			}
		}
		return kind;
	}
	
	public void setMappingKind(String mappingKind)  {
		if (!StringUtil.equalObjects(mappingKind, getMappingKind())) {
			setCustomized(MAPPING_KIND, mappingKind);
		}
	}
	
	public boolean isNullable() {
		return this.mDbColumn.isNullable();
	}

	public int getSize() {
		if ( this.mDbColumn.isNumeric()){
			return mDbColumn.getPrecision();
		}
		return mDbColumn.getLength();
	}

	public int getDecimalDigits() {
		if ( this.mDbColumn.isNumeric() ){
			return mDbColumn.getScale();
		}
		return -1;
	}
	
	public boolean isPrimaryKey() {
		return this.mDbColumn.isPartOfPrimaryKey();
	}
	
	public boolean isPartOfCompositePrimaryKey() {
		return this.mDbColumn.isPartOfPrimaryKey() &&
				this.mTable.getPrimaryKeyColumnsSize() > 1;
	}
	
	public boolean isForeignKey() {
		return this.mDbColumn.isPartOfForeignKey();
	}
	
	public boolean isUnique() {
		return this.mDbColumn.isPartOfUniqueConstraint();
	}
	
	public String getPropertyDescription() {
		return customized(PROPERTY_DESC);
	}
	
	public boolean isDataTypeLOB() {
		return this.mDbColumn.isLOB();
	}	

	public boolean isNeedMapTemporalType() {
		String propertyType = this.getPropertyType();
		return ( propertyType.equals("java.util.Date") || propertyType.equals("java.util.Calendar") );  //$NON-NLS-1$ //$NON-NLS-2$
	}	
	
	public String getTemporalType() {
		String defaultType = getCustomizer().getPropertyTypeFromColumn( this.mDbColumn );
		if( defaultType.equals("java.sql.Date")){ //$NON-NLS-1$
			return "DATE"; //$NON-NLS-1$
		}else if( defaultType.equals("java.sql.Time")){ //$NON-NLS-1$
			return "TIME"; //$NON-NLS-1$
		}else {
			return "TIMESTAMP"; //$NON-NLS-1$
		}
	}	
	
	/**
	 * Returns the generated property getter scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE}
	 * |{@link #PRIVATE_SCOPE}.
	 * This method never returns null (defaults to public).
	 */
	public String getPropertyGetScope() {
		String scope = customized(PROPERTY_GET_SCOPE);
		if (scope == null) {
			scope = PUBLIC_SCOPE;
		}
		return scope;
	}
	
	public void setPropertyGetScope(String scope) {
		if (!StringUtil.equalObjects(scope, getPropertyGetScope())) {
			setCustomized(PROPERTY_GET_SCOPE, scope);
		}
	}
	
	/**
	 * Returns the generated property setter scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE}
	 * |{@link #PRIVATE_SCOPE}.
	 * This method never returns null (defaults to public).
	 */
	public String getPropertySetScope() {
		String scope = customized(PROPERTY_SET_SCOPE);
		if (scope == null) {
			scope = PUBLIC_SCOPE;
		}
		return scope;
	}
	
	public void setPropertySetScope(String scope) {
		if (!StringUtil.equalObjects(scope, getPropertySetScope())) {
			setCustomized(PROPERTY_SET_SCOPE, scope);
		}
	}
	
	/**
	 * Returns the generated field member scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE}
	 * |{@link #PRIVATE_SCOPE}.
	 * This method never returns null (defaults to private).
	 */
	public String getFieldScope() {
		String scope = customized(FIELD_SCOPE);
		if (scope == null) {
			scope = PRIVATE_SCOPE;
		}
		return scope;
	}
	
	/**
	 * Returns true if this column should be used in the 
	 * <code>equals</code> method implementation.
	 */
	public boolean isUseInEquals()  {
		return customizedBoolean(USE_IN_EQUALS) || isPrimaryKey();
	}
	
	public void setUseInEquals(boolean value) {
		setCustomizedBoolean(USE_IN_EQUALS, value, false);
	}
	
	/**
	 * Returns true if this column should be used in the 
	 * <code>toString</code> method implementation.
	 */
	public boolean isUseInToString()  {
		return customizedBoolean(USE_IN_TO_STRING) || isPrimaryKey();
	}
	
	public void setUseInToString(boolean value) {
		setCustomizedBoolean(USE_IN_TO_STRING, value, false);
	}
	
	public boolean isUpdateable() {
		return !"false".equals(customized(UPDATEABLE)); //defaults to true //$NON-NLS-1$
	}
	
	public void setUpdateable(boolean value) {
		setCustomizedBoolean(UPDATEABLE, value, true);
	}
	
	public boolean isInsertable() {
		return !"false".equals(customized(INSERTABLE)); //defaults to true //$NON-NLS-1$
	}
	
	public void setInsertable(boolean value) {
		setCustomizedBoolean(INSERTABLE, value, true);
	}
	
	public boolean isGenerated() {
		return !"false".equals(customized(GENERATED)); //defaults to true //$NON-NLS-1$
	}
	
	public void setGenerated(boolean value) {
		setCustomizedBoolean(GENERATED, value, true);
	}
	
	@Override
	public String toString() {
		return "name=" + getName() + "; type=" + getPropertyType() ; //$NON-NLS-1$ //$NON-NLS-2$ 
	}

	/*get/set and field scopes*/
	public static final String PUBLIC_SCOPE = "public"; //$NON-NLS-1$
	public static final String PROTECTED_SCOPE = "protected"; //$NON-NLS-1$
	public static final String PRIVATE_SCOPE = "private"; //$NON-NLS-1$

	/*customization properties*/
	private static final String PROPERTY_NAME = "propertyName"; //$NON-NLS-1$
	protected static final String PROPERTY_TYPE = "propertyType"; //$NON-NLS-1$
	protected static final String MAPPING_KIND = "mappingKind"; //$NON-NLS-1$
	private static final String PROPERTY_DESC = "propertyDesc"; //$NON-NLS-1$
	private static final String PROPERTY_GET_SCOPE = "propertyGetScope"; //$NON-NLS-1$
	private static final String PROPERTY_SET_SCOPE = "propertySetScope"; //$NON-NLS-1$
	private static final String FIELD_SCOPE = "fieldScope"; //$NON-NLS-1$
	private static final String USE_IN_EQUALS = "useInEquals"; //$NON-NLS-1$
	private static final String USE_IN_TO_STRING = "useInToString"; //$NON-NLS-1$
	private static final String UPDATEABLE = "updateable"; //$NON-NLS-1$
	private static final String INSERTABLE = "insertable"; //$NON-NLS-1$
	private static final String GENERATED = "genProperty"; //$NON-NLS-1$
}
