/*******************************************************************************
 * Copyright (c) 2006, 2008 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.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.jpt.db.Column;
import org.eclipse.jpt.db.ForeignKey;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.NameTools;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;

/**
 * associate a table with the various relations that will be used when
 * generating the entity corresponding to the table
 */
class GenTable {
	private final GenScope scope;
	private final Table table;

	// these relations cannot be built until after we have built all the scope's tables
	private ManyToManyRelation joinTableRelation;
	private final ArrayList<ManyToManyRelation> ownedManyToManyRelations = new ArrayList<ManyToManyRelation>();
	private final ArrayList<ManyToManyRelation> nonOwnedManyToManyRelations = new ArrayList<ManyToManyRelation>();
	private final ArrayList<ManyToOneRelation> manyToOneRelations = new ArrayList<ManyToOneRelation>();
	private final ArrayList<OneToManyRelation> oneToManyRelations = new ArrayList<OneToManyRelation>();
	private final HashSet<Column> foreignKeyColumns = new HashSet<Column>();

	// key=column/relation; value=entity attribute (field/property) name
	private final HashMap<Object, String> attributeNames = new HashMap<Object, String>();
	// key to 'attributeNames' for the optional embedded ID attribute name
	private static final Object EMBEDDED_ID_VIRTUAL_COLUMN = new Object();


	// ********** construction/initialization **********

	GenTable(GenScope scope, Table table) {
		super();
		this.scope = scope;
		this.table = table;
	}


	// ********** package API **********

	EntityGenerator.Config getEntityConfig() {
		return this.scope.getEntityConfig();
	}

	/**
	 * examples:
	 *   GenTable(FOO) => "FOO_COLLECTION"
	 *   GenTable(foo) => "fooCollection"
	 *   GenTable(Foo) => "FooCollection"
	 */
	String getCollectionAttributeName() {
		String name = this.getName();
		String suffix = this.getEntityConfig().getCollectionAttributeNameSuffix();
		if (StringTools.stringIsUppercase(name)) {  // hmmm  ~bjv
			suffix = '_' + suffix.toUpperCase();
		}
		return name + suffix;
	}

	/**
	 * determine whether the table is a "join" table within the table's scope;
	 * this can be removed, later, if we find another table references the,
	 * seemingly, join table
	 * @see #clearJoinTableRelation() (and callers)
	 */
	void buildJoinTableRelation() {
		if ( ! this.table.isPossibleJoinTable()) {
			return;  // the table must have exactly 2 foreign keys
		}
		ForeignKey owningFK = this.table.getJoinTableOwningForeignKey();
		GenTable owningGenTable = this.scope.getGenTable(owningFK.getReferencedTable());
		if (owningGenTable == null) {
			return;  // both tables must be in the scope
		}
		ForeignKey nonOwningFK = this.table.getJoinTableNonOwningForeignKey();
		GenTable nonOwningGenTable = this.scope.getGenTable(nonOwningFK.getReferencedTable());
		if (nonOwningGenTable == null) {
			return;  // both tables must be in the scope
		}
		this.joinTableRelation = new ManyToManyRelation(
											this,
											owningFK,
											owningGenTable,
											nonOwningFK,
											nonOwningGenTable
										);
	}

	/**
	 * used by the scope to figure out whether "join" tables should be
	 * converted to "entity" tables
	 */
	void addReferencedGenTablesTo(Set<GenTable> referencedTables) {
		for (Iterator<ForeignKey> stream = this.table.foreignKeys(); stream.hasNext(); ) {
			ForeignKey fk = stream.next();
			GenTable genTable = this.scope.getGenTable(fk.getReferencedTable());
			if (genTable != null) {
				referencedTables.add(genTable);
			}
		}
	}

	/**
	 * the scope clears the join table relation if there are any references
	 * to the join table from other tables in the scope
	 */
	void clearJoinTableRelation() {
		this.joinTableRelation.clear();
		this.joinTableRelation = null;
	}

	/**
	 * find "in-scope" foreign keys
	 */
	void buildManyToOneRelations() {
		for (Iterator<ForeignKey> stream = this.table.foreignKeys(); stream.hasNext(); ) {
			ForeignKey fk = stream.next();
			GenTable referencedGenTable = this.scope.getGenTable(fk.getReferencedTable());
			if (referencedGenTable != null) {
				this.manyToOneRelations.add(new ManyToOneRelation(this, fk, referencedGenTable));
			}
		}
	}

	/**
	 * now that all the relations are in place, we can configure the Java
	 * attribute names
	 */
	void buildAttributeNames() {
		if ((this.table.primaryKeyColumnsSize() > 1) && this.getEntityConfig().generateEmbeddedIdForCompoundPK()) {
			// if we are going to generate an EmbeddedId attribute, add it to
			// 'attributeNames' so we don't collide with it later, when generating
			// attribute names for the columns etc.
			this.configureAttributeName(EMBEDDED_ID_VIRTUAL_COLUMN, this.getEntityConfig().getEmbeddedIdAttributeName());
		}

		// gather up all the table's columns...
		Set<Column> columns = CollectionTools.set(this.table.columns(), this.table.columnsSize());
		// ...remove the columns that belong exclusively to many-to-one foreign keys...
		this.buildManyToOneAttributeNames(columns);
		// ...and use the remaining columns to generate "basic" attribute names
		this.buildBasicAttributeNames(columns);

		this.buildOneToManyAttributeNames();
		this.buildOwnedManyToManyAttributeNames();
		this.buildNonOwnedManyToManyAttributeNames();
	}

	/**
	 * return the columns that are part of the table's primary key
	 * but are also part of an "in-scope" foreign key
	 */
	Iterator<Column> readOnlyPrimaryKeyColumns() {
		return new FilteringIterator<Column, Column>(this.table.primaryKeyColumns()) {
			@Override
			protected boolean accept(Column pkColumn) {
				return pkColumn.isForeignKeyColumn();
			}
		};
	}

	/**
	 * return the columns that are part of the table's primary key
	 * but are NOT part of any "in-scope" foreign key
	 */
	Iterator<Column> writablePrimaryKeyColumns() {
		return new FilteringIterator<Column, Column>(this.table.primaryKeyColumns()) {
			@Override
			protected boolean accept(Column pkColumn) {
				return ! pkColumn.isForeignKeyColumn();
			}
		};
	}

	/**
	 * return the columns that NEITHER part of the table's primary key
	 * NOR part of any foreign key
	 */
	Iterator<Column> nonPrimaryKeyBasicColumns() {
		return new FilteringIterator<Column, Column>(this.table.columns()) {
			@Override
			protected boolean accept(Column column) {
				return ! (column.isPrimaryKeyColumn() || column.isForeignKeyColumn());
			}
		};
	}

	Table getTable() {
		return this.table;
	}

	String getEntityName() {
		return this.getEntityConfig().getEntityName(this.table);
	}

	boolean isJoinTable() {
		return this.joinTableRelation != null;
	}

	void addOwnedManyToManyRelation(ManyToManyRelation relation) {
		this.ownedManyToManyRelations.add(relation);
	}

	void removeOwnedManyToManyRelation(ManyToManyRelation relation) {
		this.ownedManyToManyRelations.remove(relation);
	}

	void addNonOwnedManyToManyRelation(ManyToManyRelation relation) {
		this.nonOwnedManyToManyRelations.add(relation);
	}

	void removeNonOwnedManyToManyRelation(ManyToManyRelation relation) {
		this.nonOwnedManyToManyRelations.remove(relation);
	}

	void addOneToManyRelation(OneToManyRelation relation) {
		this.oneToManyRelations.add(relation);
	}

	Iterator<ManyToOneRelation> manyToOneRelations() {
		return this.manyToOneRelations.iterator();
	}

	Iterator<OneToManyRelation> oneToManyRelations() {
		return this.oneToManyRelations.iterator();
	}

	Iterator<ManyToManyRelation> ownedManyToManyRelations() {
		return this.ownedManyToManyRelations.iterator();
	}

	Iterator<ManyToManyRelation> nonOwnedManyToManyRelations() {
		return this.nonOwnedManyToManyRelations.iterator();
	}

	/**
	 * the key can be a column or relation or #EMBEDDED_ID_VIRTUAL_COLUMN
	 */
	private String getAttributeNameFor_(Object o) {
		return this.attributeNames.get(o);
	}

	/**
	 * this will return null if we don't want an embedded id attribute
	 */
	String getAttributeNameForEmbeddedId() {
		return this.getAttributeNameFor_(EMBEDDED_ID_VIRTUAL_COLUMN);
	}

	String getAttributeNameFor(Column column) {
		return this.getAttributeNameFor_(column);
	}

	String getAttributeNameFor(ManyToOneRelation relation) {
		return this.getAttributeNameFor_(relation);
	}

	String getAttributeNameFor(OneToManyRelation relation) {
		return this.getAttributeNameFor_(relation);
	}

	String getAttributeNameFor(ManyToManyRelation relation) {
		return this.getAttributeNameFor_(relation);
	}

	String getName() {
		return this.table.getName();
	}

	boolean joinTableNameIsDefault() {
		return this.table.joinTableNameIsDefault();
	}


	// ********** internal API **********

	/**
	 * while we are figuring out the names for the m:1 attributes, remove from the
	 * specified set of columns the columns that are only part of the foreign keys
	 * (leaving the remaining columns for basic attributes)
	 */
	private void buildManyToOneAttributeNames(Set<Column> columns) {
		for (ManyToOneRelation relation : this.manyToOneRelations) {
			CollectionTools.removeAll(columns, relation.getForeignKey().nonPrimaryKeyBaseColumns());
			CollectionTools.addAll(this.foreignKeyColumns, relation.getForeignKey().baseColumns());
			relation.setMappedBy(this.configureAttributeName(relation, relation.getAttributeName()));
		}
	}

	/**
	 * build a unique attribute name for the specified "basic" columns,
	 * checking for name collisions
	 */
	private void buildBasicAttributeNames(Set<Column> columns) {
		for (Column column : columns) {
			this.configureAttributeName(column, column.getName());
		}
	}

	private void buildOneToManyAttributeNames() {
		for (OneToManyRelation relation : this.oneToManyRelations) {
			this.configureAttributeName(relation, relation.getAttributeName());
		}
	}

	private void buildOwnedManyToManyAttributeNames() {
		for (ManyToManyRelation relation : this.ownedManyToManyRelations) {
			relation.setMappedBy(this.configureAttributeName(relation, relation.getOwnedAttributeName()));
		}
	}

	private void buildNonOwnedManyToManyAttributeNames() {
		for (ManyToManyRelation relation : this.nonOwnedManyToManyRelations) {
			this.configureAttributeName(relation, relation.getNonOwnedAttributeName());
		}
	}

	/**
	 * Convert the specified attribute name to something unique for the entity,
	 * converting it to something Java-like if the config flag is set.
	 * Store the calculated name so we can get it back later, when we
	 * are generating source.
	 */
	private String configureAttributeName(Object o, String attributeName) {
		String result = attributeName;
		Collection<String> existingAttributeNames = this.attributeNames.values();
		if (this.getEntityConfig().convertToJavaStyleIdentifiers()) {
			result = EntityGenTools.convertToUniqueJavaStyleAttributeName(result, existingAttributeNames);
		} else {
			// first, convert the attribute name to a legal Java identifier
			result = NameTools.convertToJavaIdentifier(result);
			// then make sure it's unique
			result = NameTools.uniqueNameForIgnoreCase(attributeName, existingAttributeNames);
		}
		this.attributeNames.put(o, result);
		return result;
	}

	@Override
	public String toString() {
		return StringTools.buildToStringFor(this, this.table);
	}

}
