/*******************************************************************************
 * Copyright (c) 2007, 2010 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.jpa.gen.internal;

import java.util.Collections;
import java.util.Iterator;

import org.eclipse.jpt.jpa.db.Column;
import org.eclipse.jpt.jpa.db.ForeignKey;
import org.eclipse.jpt.jpa.db.Table;
import org.eclipse.jpt.jpa.gen.internal.util.EntityGenTools;
import org.eclipse.jpt.jpa.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(), getDbName());
	}
	
	protected boolean customizedBoolean(String propName) {
		return getCustomizer().getBooleanProperty(propName, mTable.getName(), getDbName());
	}
	
	protected void setCustomized(String propName, String value) {
		if (value != null && value.length() == 0) {
			value = null;
		}
		getCustomizer().setProperty(propName, value, mTable.getName(), getDbName());
	}
	
	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(), getDbName());
		}
	}
	
	/**
	 * Returns the column name.
	 */
	public String getName() {
		String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
			buildColumnAnnotationName(mDbColumn.getName(), mDbColumn);
		return annotationName != null ? annotationName : mDbColumn.getName();
	}
	
	public String getDbName() {
		return 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(getDbName(), 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;
	}

	/**
	 * Return true if the values of name element in the @Column is default
	 * so we can skip generating the annotation
	 * 
	 * @return true
	 */
	public boolean isDefaultJoinColumnName(String associationRolePropName){
		if( !this.mDbColumn.isPartOfForeignKey()){
			return false;
		}

		Iterable<ForeignKey> it = mDbColumn.getTable().getForeignKeys();
		Iterator<ForeignKey> i = it.iterator();
		while( i.hasNext() ){
			ForeignKey fk = i.next();
			Column c = fk.getBaseColumns().iterator().next();
			if( c.equals( this.mDbColumn ) ){
				try{
					String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder().
						buildJoinColumnAnnotationName(associationRolePropName, fk );
					return annotationName==null;
				}catch(Exception e){
					//catch the case that referenced table has multiple primary key columns
					return false;
				}
			}
		}
		return false;
	}
	
	
	/**
	 * 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$
}
