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

import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.eclipse.datatools.modelbase.sql.constraints.PrimaryKey;
import org.eclipse.datatools.modelbase.sql.tables.BaseTable;
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.iterators.ArrayIterator;
import org.eclipse.jpt.utility.internal.iterators.TransformationIterator;

import com.ibm.icu.text.Collator;

/**
 *  Wrap a DTP Table
 */
final class DTPTableWrapper
	extends DTPDatabaseObjectWrapper
	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, dtpTable);
		this.dtpTable = dtpTable;
	}


	// ********** DTPWrapper implementation **********

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


	// ********** Table implementation **********

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

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

	// ***** columns

	public Iterator<Column> columns() {
		return new ArrayIterator<Column>(this.getColumns());
	}

	private Iterator<DTPColumnWrapper> columnWrappers() {
		return new ArrayIterator<DTPColumnWrapper>(this.getColumns());
	}

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

	private DTPColumnWrapper[] buildColumns() {
		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 CollectionTools.sort(result, this.buildColumnComparator());
	}

	private Comparator<Column> buildColumnComparator() {
		return new Comparator<Column>() {
			public int compare(Column column1, Column column2) {
				return Collator.getInstance().compare(column1.getName(), column2.getName());
			}
		};
	}

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

	public int columnsSize() {
		return this.getColumns().length;
	}

	public DTPColumnWrapper getColumnNamed(String name) {
		return this.selectDatabaseObjectNamed(this.getColumns(), 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);
	}

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

	public Iterator<String> sortedColumnIdentifiers() {
		// the columns are already sorted
		return new TransformationIterator<DTPColumnWrapper, String>(this.columnWrappers()) {
			@Override
			protected String transform(DTPColumnWrapper next) {
				 return next.getIdentifier();
			}
		};
	}

	public DTPColumnWrapper getColumnForIdentifier(String identifier) {
		return this.selectDatabaseObjectForIdentifier(this.getColumns(), identifier);
	}

	// ***** primaryKeyColumns

	public Iterator<Column> primaryKeyColumns() {
		return new ArrayIterator<Column>(this.getPrimaryKeyColumns());
	}

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

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

	private DTPColumnWrapper[] buildPrimaryKeyColumns() {
		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 primaryKeyColumnsSize() {
		return this.getPrimaryKeyColumns().length;
	}

	boolean primaryKeyColumnsContains(Column column) {
		return CollectionTools.contains(this.getPrimaryKeyColumns(), column);
	}

	// ***** foreignKeys

	public Iterator<ForeignKey> foreignKeys() {
		return new ArrayIterator<ForeignKey>(this.getForeignKeys());
	}

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

	private DTPForeignKeyWrapper[] buildForeignKeys() {
		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 foreignKeysSize() {
		return this.getForeignKeys().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.getForeignKeys()) {
			if (fkWrapper.baseColumnsContains(column)) {
				return true;
			}
		}
		return false;
	}

	// ***** join table

	public boolean isPossibleJoinTable() {
		if (this.getForeignKeys().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 FOO_BAR and it joins tables FOO and BAR,
	 * return the foreign key to FOO;
	 * if the table name is BAR_FOO and it joins tables FOO and BAR,
	 * return the foreign key to BAR;
	 * otherwise simply return the first foreign key in the array.
	 */
	public ForeignKey getJoinTableOwningForeignKey() {
		ForeignKey fk0 = this.getForeignKeys()[0];
		String name0 = fk0.getReferencedTable().getName();

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

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

	public ForeignKey getJoinTableNonOwningForeignKey() {
		ForeignKey fk0 = this.getForeignKeys()[0];
		ForeignKey fk1 = this.getForeignKeys()[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();
	}


	// ********** internal methods **********

	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;
	}

}
