/*******************************************************************************
 * Copyright (c) 2006, 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.core.internal.context.orm;

import java.util.Iterator;
import java.util.List;
import org.eclipse.jpt.core.MappingKeys;
import org.eclipse.jpt.core.context.AttributeMapping;
import org.eclipse.jpt.core.context.BaseColumn;
import org.eclipse.jpt.core.context.Converter;
import org.eclipse.jpt.core.context.NamedColumn;
import org.eclipse.jpt.core.context.orm.OrmAttributeMapping;
import org.eclipse.jpt.core.context.orm.OrmColumn;
import org.eclipse.jpt.core.context.orm.OrmColumnMapping;
import org.eclipse.jpt.core.context.orm.OrmConverter;
import org.eclipse.jpt.core.context.orm.OrmGeneratedValue;
import org.eclipse.jpt.core.context.orm.OrmGeneratorContainer;
import org.eclipse.jpt.core.context.orm.OrmIdMapping;
import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute;
import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationDescriptionMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.core.jpa2.context.IdMapping2_0;
import org.eclipse.jpt.core.jpa2.context.SingleRelationshipMapping2_0;
import org.eclipse.jpt.core.resource.orm.Attributes;
import org.eclipse.jpt.core.resource.orm.OrmFactory;
import org.eclipse.jpt.core.resource.orm.XmlColumn;
import org.eclipse.jpt.core.resource.orm.XmlGeneratedValue;
import org.eclipse.jpt.core.resource.orm.XmlId;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.utility.internal.iterables.CompositeIterable;
import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.utility.internal.iterables.SubIterableWrapper;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;

public abstract class AbstractOrmIdMapping<T extends XmlId>
	extends AbstractOrmAttributeMapping<T>
	implements OrmIdMapping, IdMapping2_0
{
	protected final OrmColumn column;
	
	/* 2.0 feature - a relationship may map this id */
	protected boolean mappedByRelationship;
	
	protected OrmGeneratedValue generatedValue;
	
	protected OrmConverter converter;
	
	protected final OrmConverter nullConverter;
	
	protected final OrmGeneratorContainer generatorContainer;
	
	
	protected AbstractOrmIdMapping(OrmPersistentAttribute parent, T resourceMapping) {
		super(parent, resourceMapping);
		this.column = getXmlContextNodeFactory().buildOrmColumn(this, this);
		this.column.initialize(this.resourceAttributeMapping.getColumn());//TODO pass in to constructor
		this.mappedByRelationship = calculateMappedByRelationship();
		this.generatorContainer = buildGeneratorContainer();
		this.initializeGeneratedValue();
		this.nullConverter = this.getXmlContextNodeFactory().buildOrmNullConverter(this);
		this.converter = this.buildConverter(this.getResourceConverterType());
	}
	
	
	protected OrmGeneratorContainer buildGeneratorContainer() {
		return getXmlContextNodeFactory().buildOrmGeneratorContainer(this, this.resourceAttributeMapping);
	}
	
	public String getKey() {
		return MappingKeys.ID_ATTRIBUTE_MAPPING_KEY;
	}
	
	public int getXmlSequence() {
		return 0;
	}
	
	public void initializeOn(OrmAttributeMapping newMapping) {
		newMapping.initializeFromOrmIdMapping(this);
	}
	
	@Override
	public void initializeFromOrmColumnMapping(OrmColumnMapping oldMapping) {
		super.initializeFromOrmColumnMapping(oldMapping);
		getColumn().initializeFrom(oldMapping.getColumn());
	}
	
	public OrmColumn getColumn() {
		return this.column;
	}
	
	public OrmConverter getConverter() {
		return this.converter;
	}
	
	protected String getConverterType() {
		return this.converter.getType();
	}
	
	public void setConverter(String converterType) {
		if (this.valuesAreEqual(getConverterType(), converterType)) {
			return;
		}
		OrmConverter oldConverter = this.converter;
		OrmConverter newConverter = buildConverter(converterType);
		this.converter = this.nullConverter;
		if (oldConverter != null) {
			oldConverter.removeFromResourceModel();
		}
		this.converter = newConverter;
		if (newConverter != null) {
			newConverter.addToResourceModel();
		}
		firePropertyChanged(CONVERTER_PROPERTY, oldConverter, newConverter);
	}
	
	protected void setConverter(OrmConverter newConverter) {
		OrmConverter oldConverter = this.converter;
		this.converter = newConverter;
		firePropertyChanged(CONVERTER_PROPERTY, oldConverter, newConverter);
	}
	
	public OrmGeneratedValue addGeneratedValue() {
		if (getGeneratedValue() != null) {
			throw new IllegalStateException("gemeratedValue already exists"); //$NON-NLS-1$
		}
		XmlGeneratedValue resourceGeneratedValue = OrmFactory.eINSTANCE.createXmlGeneratedValue();
		this.generatedValue = buildGeneratedValue(resourceGeneratedValue);
		this.resourceAttributeMapping.setGeneratedValue(resourceGeneratedValue);
		firePropertyChanged(GENERATED_VALUE_PROPERTY, null, this.generatedValue);
		return this.generatedValue;
	}
	
	public void removeGeneratedValue() {
		if (getGeneratedValue() == null) {
			throw new IllegalStateException("gemeratedValue does not exist, cannot be removed"); //$NON-NLS-1$
		}
		OrmGeneratedValue oldGeneratedValue = this.generatedValue;
		this.generatedValue = null;
		this.resourceAttributeMapping.setGeneratedValue(null);
		firePropertyChanged(GENERATED_VALUE_PROPERTY, oldGeneratedValue, null);
	}
	
	public OrmGeneratedValue getGeneratedValue() {
		return this.generatedValue;
	}
	
	protected void setGeneratedValue(OrmGeneratedValue newGeneratedValue) {
		OrmGeneratedValue oldGeneratedValue = this.generatedValue;
		this.generatedValue = newGeneratedValue;
		firePropertyChanged(GENERATED_VALUE_PROPERTY, oldGeneratedValue, newGeneratedValue);
	}
	
	public OrmGeneratorContainer getGeneratorContainer() {
		return this.generatorContainer;
	}
	
	@Override
	public String getPrimaryKeyColumnName() {
		return this.getColumn().getName();
	}
	
	@Override
	public boolean isOverridableAttributeMapping() {
		return true;
	}
	
	public void addToResourceModel(Attributes resourceAttributes) {
		resourceAttributes.getIds().add(this.resourceAttributeMapping);
	}
	
	public void removeFromResourceModel(Attributes resourceAttributes) {
		resourceAttributes.getIds().remove(this.resourceAttributeMapping);
	}
	
	
	//***************** XmlColumn.Owner implementation ****************
	
	public XmlColumn getResourceColumn() {
		return this.resourceAttributeMapping.getColumn();
	}
	
	protected boolean isColumnSpecified() {
		return ! isVirtual() && getResourceColumn() != null;
	}
	
	public void addResourceColumn() {
		this.resourceAttributeMapping.setColumn(OrmFactory.eINSTANCE.createXmlColumn());
	}
	
	public void removeResourceColumn() {
		this.resourceAttributeMapping.setColumn(null);
	}
	
	
	//************** NamedColumn.Owner implementation ***************
	
	public Table getDbTable(String tableName) {
		return getTypeMapping().getDbTable(tableName);
	}
	
	public String getDefaultColumnName() {		
		return (isMappedByRelationship() && ! isColumnSpecified()) ? null : getName();
	}
	
	
	//************** BaseColumn.Owner implementation ***************
	
	public String getDefaultTableName() {
		return (isMappedByRelationship() && ! isColumnSpecified()) ? null : getTypeMapping().getPrimaryTableName();
	}
	
	public boolean tableNameIsInvalid(String tableName) {
		return getTypeMapping().tableNameIsInvalid(tableName);
	}
	
	public Iterator<String> candidateTableNames() {
		return getTypeMapping().associatedTableNamesIncludingInherited();
	}
	
	
	// **************** IdColumn2_0 impl **************************************
	
	public boolean isMappedByRelationship() {
		return this.mappedByRelationship;
	}
	
	protected void setMappedByRelationship(boolean newValue) {
		boolean oldValue = this.mappedByRelationship;
		this.mappedByRelationship = newValue;
		firePropertyChanged(MAPPED_BY_RELATIONSHIP_PROPERTY, oldValue, newValue);
	}
	
	protected boolean calculateMappedByRelationship() {
		for (SingleRelationshipMapping2_0 each : getMapsIdRelationships()) {
			if (each.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getResolvedAttributeMappingValue() == this) {
				return true;
			}
		}
		return false;
	}
	
	protected Iterable<SingleRelationshipMapping2_0> getMapsIdRelationships() {
		return new FilteringIterable<SingleRelationshipMapping2_0>(
				new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>(
					new CompositeIterable<AttributeMapping>(
						getTypeMapping().getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY),
						getTypeMapping().getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) {
			@Override
			protected boolean accept(SingleRelationshipMapping2_0 o) {
				return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy();
			}
		};
	}
	
	
	protected void initializeGeneratedValue() {
		if (this.resourceAttributeMapping.getGeneratedValue() != null) {
			this.generatedValue = buildGeneratedValue(this.resourceAttributeMapping.getGeneratedValue());
		}
	}
	
	protected OrmGeneratedValue buildGeneratedValue(XmlGeneratedValue resourceGeneratedValue) {
		return getXmlContextNodeFactory().buildOrmGeneratedValue(this, resourceGeneratedValue);
	}
	
	@Override
	public void update() {
		super.update();
		this.column.update(getResourceColumn());
		setMappedByRelationship(calculateMappedByRelationship());
		this.generatorContainer.update();
		this.updateGeneratedValue();
		if (this.valuesAreEqual(getResourceConverterType(), getConverterType())) {
			getConverter().update();
		}
		else {
			setConverter(buildConverter(getResourceConverterType()));
		}
	}
	
	protected void updateGeneratedValue() {
		if (this.resourceAttributeMapping.getGeneratedValue() == null) {
			if (getGeneratedValue() != null) {
				setGeneratedValue(null);
			}
		}
		else {
			if (getGeneratedValue() == null) {
				setGeneratedValue(buildGeneratedValue(this.resourceAttributeMapping.getGeneratedValue()));
			}
			else {
				getGeneratedValue().update(this.resourceAttributeMapping.getGeneratedValue());
			}
		}
	}
	
	protected OrmConverter buildConverter(String converterType) {
		if (this.valuesAreEqual(converterType, Converter.NO_CONVERTER)) {
			return this.nullConverter;
		}
		if (this.valuesAreEqual(converterType, Converter.TEMPORAL_CONVERTER)) {
			return getXmlContextNodeFactory().buildOrmTemporalConverter(this, this.resourceAttributeMapping);
		}
		return null;
	}
	
	protected String getResourceConverterType() {
		if (this.resourceAttributeMapping.getTemporal() != null) {
			return Converter.TEMPORAL_CONVERTER;
		}
		return Converter.NO_CONVERTER;
	}
	
	
	// ****************** validation ****************

	@Override
	public void validate(List<IMessage> messages, IReporter reporter) {
		super.validate(messages, reporter);
		
		// [JPA 2.0] if the column is specified, or if the id is not mapped by a relationship,
		// then the column is validated.
		// (In JPA 1.0, the column will always be validated, since the id is never mapped by a
		//  relationship)
		if (isColumnSpecified() || ! isMappedByRelationship()) {
			getColumn().validate(messages, reporter);
		}
		
		// [JPA 2.0] if the column is specified and the id is mapped by a relationship, 
		// then that is an error
		// (In JPA 1.0, this will never be the case, since the id is never mapped by a relationship)
		if (isColumnSpecified() && isMappedByRelationship()) {
			messages.add(
					DefaultJpaValidationMessages.buildMessage(
						IMessage.HIGH_SEVERITY,
						JpaValidationMessages.ID_MAPPING_MAPPED_BY_RELATIONSHIP_AND_COLUMN_SPECIFIED,
						new String[] {},
						getColumn(),
						getColumn().getValidationTextRange()));
		}
		
		if (this.generatedValue != null) {
			this.generatedValue.validate(messages, reporter);
		}
		this.generatorContainer.validate(messages, reporter);
	}

	public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) {
		if (isVirtual()) {
			return this.buildVirtualUnresolvedNameMessage(column, textRange);
		}
		return DefaultJpaValidationMessages.buildMessage(
			IMessage.HIGH_SEVERITY,
			JpaValidationMessages.COLUMN_UNRESOLVED_NAME,
			new String[] {column.getName(), column.getDbTable().getName()}, 
			column,
			textRange
		);
	}

	protected IMessage buildVirtualUnresolvedNameMessage(NamedColumn column, TextRange textRange) {
		return DefaultJpaValidationMessages.buildMessage(
			IMessage.HIGH_SEVERITY,
			JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLUMN_UNRESOLVED_NAME,
			new String[] {getName(), column.getName(), column.getDbTable().getName()},
			column, 
			textRange
		);
	}

	public IMessage buildTableNotValidMessage(BaseColumn column, TextRange textRange) {
		if (isVirtual()) {
			return this.buildVirtualTableNotValidMessage(column, textRange);
		}
		return DefaultJpaValidationMessages.buildMessage(
			IMessage.HIGH_SEVERITY,
			JpaValidationMessages.COLUMN_TABLE_NOT_VALID,
			new String[] {
				column.getTable(),
				column.getName(),
				JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY}, 
			column, 
			textRange
		);
	}
	
	public IMessage buildVirtualTableNotValidMessage(BaseColumn column, TextRange textRange) {
		return DefaultJpaValidationMessages.buildMessage(
			IMessage.HIGH_SEVERITY,
			JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLUMN_TABLE_NOT_VALID,
			new String[] {
				getName(),
				column.getTable(),
				column.getName(),
				JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY},
			column, 
			textRange
		);
	}
}
