/*******************************************************************************
 * Copyright (c) 2006, 2011 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.db.internal;

import java.util.List;

import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject;
import org.eclipse.datatools.modelbase.sql.constraints.PrimaryKey;
import org.eclipse.datatools.modelbase.sql.tables.BaseTable;
import org.eclipse.jpt.common.utility.internal.ArrayTools;
import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.jpa.db.Column;
import org.eclipse.jpt.jpa.db.DatabaseObject;
import org.eclipse.jpt.jpa.db.ForeignKey;
import org.eclipse.jpt.jpa.db.Table;

/**
 *  Wrap a DTP Table
 */
final class DTPTableWrapper
	extends DTPDatabaseObjectWrapper<DTPSchemaWrapper>
	implements Table
{
	/** the wrapped DTP table */
	private final org.eclipse.datatools.modelbase.sql.tables.Table dtpTable;

	/** lazy-initialized */
	private DTPColumnWrapper[] columns;

	/** lazy-initialized */
	private DTPColumnWrapper[] primaryKeyColumns;

	/** lazy-initialized */
	private DTPForeignKeyWrapper[] foreignKeys;


	private static final DTPColumnWrapper[] EMPTY_COLUMNS = new DTPColumnWrapper[0];
	private static final DTPForeignKeyWrapper[] EMPTY_FOREIGN_KEYS = new DTPForeignKeyWrapper[0];


	// ********** constructor **********

	DTPTableWrapper(DTPSchemaWrapper schema, org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) {
		super(schema);
		this.dtpTable = dtpTable;
	}


	// ********** columns **********

	public Iterable<Column> getColumns() {
		return new ArrayIterable<Column>(this.getColumnArray());
	}

	private Iterable<DTPColumnWrapper> getColumnWrappers() {
		return new ArrayIterable<DTPColumnWrapper>(this.getColumnArray());
	}

	private synchronized DTPColumnWrapper[] getColumnArray() {
		if (this.columns == null) {
			this.columns = this.buildColumnArray();
		}
		return this.columns;
	}

	private DTPColumnWrapper[] buildColumnArray() {
		List<org.eclipse.datatools.modelbase.sql.tables.Column> dtpColumns = this.getDTPColumns();
		DTPColumnWrapper[] result = new DTPColumnWrapper[dtpColumns.size()];
		for (int i = result.length; i-- > 0;) {
			result[i] = new DTPColumnWrapper(this, dtpColumns.get(i));
		}
		return ArrayTools.sort(result, DEFAULT_COMPARATOR);
	}

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	private List<org.eclipse.datatools.modelbase.sql.tables.Column> getDTPColumns() {
		return this.dtpTable.getColumns();
	}

	public int getColumnsSize() {
		return this.getColumnArray().length;
	}

	public DTPColumnWrapper getColumnNamed(String name) {
		return this.selectDatabaseObjectNamed(this.getColumnWrappers(), name);
	}

	/**
	 * Return the column for the specified DTP column.
	 */
	DTPColumnWrapper getColumn(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) {
		// try to short-circuit the search
		return this.wraps(dtpColumn.getTable()) ?
						this.getColumn_(dtpColumn) :
						this.getSchema().getColumn(dtpColumn);
	}

	/**
	 * Pre-condition: The table contains the specified column.
	 */
	DTPColumnWrapper getColumn_(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) {
		for (DTPColumnWrapper column : this.getColumnArray()) {
			if (column.wraps(dtpColumn)) {
				return column;
			}
		}
		throw new IllegalArgumentException("invalid DTP column: " + dtpColumn);  //$NON-NLS-1$
	}

	public Iterable<String> getSortedColumnIdentifiers() {
		// the columns are already sorted
		return new TransformationIterable<DatabaseObject, String>(this.getColumnWrappers(), IDENTIFIER_TRANSFORMER);
	}

	public Column getColumnForIdentifier(String identifier) {
		return this.getDTPDriverAdapter().selectColumnForIdentifier(this.getColumns(), identifier);
	}


	// ********** primary key columns **********

	public Iterable<Column> getPrimaryKeyColumns() {
		return new ArrayIterable<Column>(this.getPrimaryKeyColumnArray());
	}

	public DTPColumnWrapper getPrimaryKeyColumn() {
		DTPColumnWrapper[] pkColumns = this.getPrimaryKeyColumnArray();
		if (pkColumns.length != 1) {
			throw new IllegalStateException("multiple primary key columns: " + pkColumns.length);  //$NON-NLS-1$
		}
		return pkColumns[0];
	}

	private synchronized DTPColumnWrapper[] getPrimaryKeyColumnArray() {
		if (this.primaryKeyColumns == null) {
			this.primaryKeyColumns = this.buildPrimaryKeyColumnArray();
		}
		return this.primaryKeyColumns;
	}

	private DTPColumnWrapper[] buildPrimaryKeyColumnArray() {
		if ( ! (this.dtpTable instanceof BaseTable)) {
			return EMPTY_COLUMNS;
		}
		PrimaryKey pk = ((BaseTable) this.dtpTable).getPrimaryKey();
		if (pk == null) {
			// no PK was defined
			return EMPTY_COLUMNS;
		}
		List<org.eclipse.datatools.modelbase.sql.tables.Column> pkColumns = this.getColumns(pk);
		DTPColumnWrapper[] result = new DTPColumnWrapper[pkColumns.size()];
		for (int i = result.length; i-- > 0;) {
			result[i] = this.getColumn(pkColumns.get(i));
		}
		return result;
	}

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	private List<org.eclipse.datatools.modelbase.sql.tables.Column> getColumns(PrimaryKey pk) {
		return pk.getMembers();
	}

	public int getPrimaryKeyColumnsSize() {
		return this.getPrimaryKeyColumnArray().length;
	}

	boolean primaryKeyColumnsContains(Column column) {
		return ArrayTools.contains(this.getPrimaryKeyColumnArray(), column);
	}


	// ********** foreign keys **********

	public Iterable<ForeignKey> getForeignKeys() {
		return new ArrayIterable<ForeignKey>(this.getForeignKeyArray());
	}

	private synchronized DTPForeignKeyWrapper[] getForeignKeyArray() {
		if (this.foreignKeys == null) {
			this.foreignKeys = this.buildForeignKeyArray();
		}
		return this.foreignKeys;
	}

	private DTPForeignKeyWrapper[] buildForeignKeyArray() {
		if ( ! (this.dtpTable instanceof BaseTable)) {
			return EMPTY_FOREIGN_KEYS;
		}
		List<org.eclipse.datatools.modelbase.sql.constraints.ForeignKey> dtpForeignKeys = this.getDTPForeignKeys();
		DTPForeignKeyWrapper[] result = new DTPForeignKeyWrapper[dtpForeignKeys.size()];
		for (int i = result.length; i-- > 0;) {
			result[i] = new DTPForeignKeyWrapper(this, dtpForeignKeys.get(i));
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	private List<org.eclipse.datatools.modelbase.sql.constraints.ForeignKey> getDTPForeignKeys() {
		return ((BaseTable) this.dtpTable).getForeignKeys();
	}

	public int getForeignKeysSize() {
		return this.getForeignKeyArray().length;
	}

	/**
	 * return whether the specified column is a base column for at least one
	 * of the the table's foreign keys
	 */
	boolean foreignKeyBaseColumnsContains(Column column) {
		for (DTPForeignKeyWrapper fkWrapper : this.getForeignKeyArray()) {
			if (fkWrapper.baseColumnsContains(column)) {
				return true;
			}
		}
		return false;
	}


	// ********** join table **********

	public boolean isPossibleJoinTable() {
		if (this.getForeignKeyArray().length != 2) {
			return false;  // the table must have exactly 2 foreign keys
		}
		for (Column column : this.getColumns()) {
			if ( ! this.foreignKeyBaseColumnsContains(column)) {
				return false;  // all the table's columns must belong to one (or both) of the 2 foreign keys
			}
		}
		return true;
	}

	/**
	 * If the table name is <code>FOO_BAR</code>
	 * and it joins tables <code>FOO</code> and <code>BAR</code>,
	 * return the foreign key to <code>FOO</code>;
	 * if the table name is <code>BAR_FOO</code>
	 * and it joins tables <code>FOO</code> and <code>BAR</code>,
	 * return the foreign key to <code>BAR</code>;
	 * otherwise simply return the first foreign key in the array.
	 */
	public ForeignKey getJoinTableOwningForeignKey() {
		ForeignKey fk0 = this.getForeignKeyArray()[0];
		String name0 = fk0.getReferencedTable().getName();

		ForeignKey fk1 = this.getForeignKeyArray()[1];
		String name1 = fk1.getReferencedTable().getName();

		return this.getName().equals(name1 + '_' + name0) ? fk1 : fk0;
	}

	public ForeignKey getJoinTableNonOwningForeignKey() {
		ForeignKey fk0 = this.getForeignKeyArray()[0];
		ForeignKey fk1 = this.getForeignKeyArray()[1];
		ForeignKey ofk = this.getJoinTableOwningForeignKey();
		return (ofk == fk0) ? fk1 : fk0;
	}

	/**
	 * Hmmm....
	 * We might want to go to the platform to allow a vendor-specific
	 * comparison here;
	 * but, since all the names are coming directly from the database
	 * (i.e. there are no conversions to Java identifiers etc.), it seems
	 * like we can just compare them directly and ignore case-sensitivity
	 * issues....  ~bjv
	 */
	public boolean joinTableNameIsDefault() {
		return this.getName().equals(this.buildDefaultJoinTableName());
	}

	private String buildDefaultJoinTableName() {
		return this.getJoinTableOwningTable().getName()
					+ '_'
					+ this.getJoinTableNonOwningTable().getName();
	}

	private Table getJoinTableOwningTable() {
		return this.getJoinTableOwningForeignKey().getReferencedTable();
	}

	private Table getJoinTableNonOwningTable() {
		return this.getJoinTableNonOwningForeignKey().getReferencedTable();
	}


	// ********** misc **********

	public DTPSchemaWrapper getSchema() {
		return this.parent;
	}

	public String getName() {
		return this.dtpTable.getName();
	}

	@Override
	ICatalogObject getCatalogObject() {
		return (ICatalogObject) this.dtpTable;
	}

	@Override
	synchronized void catalogObjectChanged() {
		super.catalogObjectChanged();
		this.getConnectionProfile().tableChanged(this);
	}

	boolean wraps(org.eclipse.datatools.modelbase.sql.tables.Table table) {
		return this.dtpTable == table;
	}

	/**
	 * Return the table for the specified DTP table.
	 */
	DTPTableWrapper getTable(org.eclipse.datatools.modelbase.sql.tables.Table table) {
		// try to short-circuit the search
		return this.wraps(table) ? this : this.getSchema().getTable(table);
	}


	// ********** listening **********

	@Override
	synchronized void startListening() {
		if (this.foreignKeys != null) {
			this.startForeignKeys();
		}
		if (this.columns != null) {
			this.startColumns();
		}
		super.startListening();
	}

	private void startForeignKeys() {
		for (DTPForeignKeyWrapper foreignKey : this.foreignKeys) {
			foreignKey.startListening();
		}
	}

	private void startColumns() {
		for (DTPColumnWrapper column : this.columns) {
			column.startListening();
		}
	}

	@Override
	synchronized void stopListening() {
		if (this.foreignKeys != null) {
			this.stopForeignKeys();
		}
		if (this.columns != null) {
			this.stopColumns();
		}
		super.stopListening();
	}

	private void stopForeignKeys() {
		for (DTPForeignKeyWrapper foreignKey : this.foreignKeys) {
			foreignKey.stopListening();
		}
	}

	private void stopColumns() {
		for (DTPColumnWrapper column : this.columns) {
			column.stopListening();
		}
	}


	// ********** clear **********

	@Override
	synchronized void clear() {
		if (this.foreignKeys != null) {
			this.clearForeignKeys();
		}

		// the table does not "contain" the pk columns, so no need to forward #clear()
		this.primaryKeyColumns = null;

		if (this.columns != null) {
			this.clearColumns();
		}
	}

	private void clearForeignKeys() {
		this.stopForeignKeys();
		for (DTPForeignKeyWrapper foreignKey : this.foreignKeys) {
			foreignKey.clear();
		}
    	this.foreignKeys = null;
	}

	private void clearColumns() {
		this.stopColumns();
		for (DTPColumnWrapper column : this.columns) {
			column.clear();
		}
    	this.columns = null;
	}
}
