/*******************************************************************************
 * 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.db.internal;

import java.text.Collator;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject;
import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObjectListener;
import org.eclipse.datatools.modelbase.sql.constraints.PrimaryKey;
import org.eclipse.datatools.modelbase.sql.tables.BaseTable;
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.TransformationIterator;

/**
 *  Wrap a DTP Table
 */
public final class Table extends DTPWrapper implements Comparable<Table> {
	final Schema schema;
	final org.eclipse.datatools.modelbase.sql.tables.Table dtpTable;
	private ICatalogObjectListener tableListener;
	
	private Set<Column> columns;  // lazy-initialized
	private Set<Column> primaryKeyColumns;  // lazy-initialized
	private Set<ForeignKey> foreignKeys;  // lazy-initialized
	private Set<Column> foreignKeyColumns;  // lazy-initialized
	
	// ********** constructors **********

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


	// ********** behavior **********

	private void initialize() {
		if( this.connectionIsOnline()) {
			this.tableListener = this.buildTableListener();
			this.addCatalogObjectListener(( ICatalogObject) this.dtpTable, this.tableListener);
		}
	}
	
	@Override
	protected boolean connectionIsOnline() {
		return this.schema.connectionIsOnline();
	}
	
	private ICatalogObjectListener buildTableListener() {
       return new ICatalogObjectListener() {
    	    public void notifyChanged( final ICatalogObject table, final int eventType) {     
    			if( table == Table.this.dtpTable) {	    	    	
    				Table.this.refresh();
	    			Table.this.schema.tableChanged( Table.this, eventType);
    			}
    	    }
        };
    }

    void refresh() {
		this.disposeColumns();
		
    	this.columns = null;
    	this.primaryKeyColumns = null;
    	this.foreignKeys = null;
    	this.foreignKeyColumns = null;
    }

	@Override
	protected void dispose() {
		this.removeCatalogObjectListener(( ICatalogObject) this.dtpTable, this.tableListener);
		
		this.disposeColumns();
		this.disposeForeignKey();
	}

	private void disposeColumns() {
		if( this.columns != null) {
			for( Iterator<Column> stream = this.columns(); stream.hasNext(); ) {
				stream.next().dispose();
			}
		}
	}

	private void disposeForeignKey() {
		if( this.foreignKeys != null) {
			for( Iterator<ForeignKey> stream = this.foreignKeys(); stream.hasNext(); ) {
				stream.next().dispose();
			}
		}
	}

	// ********** queries **********

	@Override
	public String getName() {
		return this.dtpTable.getName();
	}
	
	boolean isCaseSensitive() {
		return this.schema.isCaseSensitive();
	}

	public String shortJavaClassName() {
		String jName = this.getName();
		if ( ! this.isCaseSensitive()) {
			jName = StringTools.capitalize(jName.toLowerCase());
		}
		return NameTools.convertToJavaIdentifier(jName);
	}

	public boolean matchesShortJavaClassName(String shortJavaClassName) {
		return this.isCaseSensitive() ?
			this.getName().equals(shortJavaClassName)
		:
			this.getName().equalsIgnoreCase(shortJavaClassName);
	}

	public String javaFieldName() {
		String jName = this.getName();
		if ( ! this.isCaseSensitive()) {
			jName = jName.toLowerCase();
		}
		return NameTools.convertToJavaIdentifier(jName);
	}

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

	/**
	 * return the table for the specified DTP table
	 */
	Table table(org.eclipse.datatools.modelbase.sql.tables.Table table) {
		return this.schema.table(table);
	}

	public Database database() {
		return this.schema.database();
	}

	// ***** columns

	private synchronized Set<Column> getColumns() {
		if (this.columns == null) {
			this.columns = this.buildColumns();
		}
		return this.columns;
	}

	@SuppressWarnings("unchecked")
	private Collection<org.eclipse.datatools.modelbase.sql.tables.Column> dtpColumns() {
		return this.dtpTable.getColumns();
	}

	private Set<Column> buildColumns() {
		Collection<org.eclipse.datatools.modelbase.sql.tables.Column> dtpColumns = this.dtpColumns();
		Set<Column> result = new HashSet<Column>(dtpColumns.size());
		for (org.eclipse.datatools.modelbase.sql.tables.Column c : dtpColumns) {
			result.add(new Column(this, c));
		}
		return result;
	}

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

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

	public boolean columnsContains(Column column) {
		return this.getColumns().contains(column);
	}

	public Iterator<String> columnNames() {
		return new TransformationIterator<Column, String>(this.columns()) {
			@Override
			protected String transform(Column next) {
				 return next.getName();
			}
		};
	}

	public boolean containsColumnNamed(String name) {
		return this.columnNamed(name) != null;
	}

	public Column columnNamed(String name) {
		return this.isCaseSensitive() ? this.columnNamedInternal(name) : this.columnNamedIgnoreCase(name);
	}
	
	private Column columnNamedInternal(String name) {
		for (Iterator<Column> stream = this.columns(); stream.hasNext(); ) {
			Column column = stream.next();
			if (column.getName().equals(name)) {
				return column;
			}
		}
		return null;
	}

	private Column columnNamedIgnoreCase(String name) {
		for (Iterator<Column> stream = this.columns(); stream.hasNext(); ) {
			Column column = stream.next();
			if (StringTools.stringsAreEqualIgnoreCase(column.getName(), name)) {
				return column;
			}
		}
		return null;
	}
	
	/**
	 * return the column for the specified dtp column
	 */
	Column column(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) {
		if (dtpColumn.getTable() != this.dtpTable) {
			return this.schema.column(dtpColumn);
		}
		for (Iterator<Column> stream = this.columns(); stream.hasNext(); ) {
			Column column = stream.next();
			if (column.wraps(dtpColumn)) {
				return column;
			}
		}
		throw new IllegalArgumentException("invalid dtp column: " + dtpColumn);
	}


	// ***** primaryKeyColumns

	private synchronized Set<Column> getPrimaryKeyColumns() {
		if (this.primaryKeyColumns == null) {
			this.primaryKeyColumns = this.buildPrimaryKeyColumns();
		}
		return this.primaryKeyColumns;
	}

	@SuppressWarnings("unchecked")
	private Collection<org.eclipse.datatools.modelbase.sql.tables.Column> columns(PrimaryKey pk) {
		return pk.getMembers();
	}

	private Set<Column> buildPrimaryKeyColumns() {
		if ( ! (this.dtpTable instanceof BaseTable)) {
			return Collections.emptySet();
		}
		PrimaryKey pk = ((BaseTable) this.dtpTable).getPrimaryKey();
		if (pk == null) {
			// no PK was defined
			return Collections.emptySet();
		}
		Collection<org.eclipse.datatools.modelbase.sql.tables.Column> pkColumns = this.columns(pk);
		Set<Column> result = new HashSet<Column>(pkColumns.size());
		for (org.eclipse.datatools.modelbase.sql.tables.Column pkColumn : pkColumns) {
			result.add(this.column(pkColumn));
		}
		return result;
	}

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

	public int primaryKeyColumnsSize() {
		return this.getPrimaryKeyColumns().size();
	}

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


	// ***** foreignKeys

	private synchronized Set<ForeignKey> getForeignKeys() {
		if (this.foreignKeys == null) {
			this.foreignKeys = this.buildForeignKeys();
		}
		return this.foreignKeys;
	}

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

	private Set<ForeignKey> buildForeignKeys() {
		if ( ! (this.dtpTable instanceof BaseTable)) {
			return Collections.emptySet();
		}
		Collection<org.eclipse.datatools.modelbase.sql.constraints.ForeignKey> dtpForeignKeys = this.dtpForeignKeys();
		Set<ForeignKey> result = new HashSet<ForeignKey>(dtpForeignKeys.size());
		for (org.eclipse.datatools.modelbase.sql.constraints.ForeignKey dtpForeignKey : dtpForeignKeys) {
			result.add(new ForeignKey(this, dtpForeignKey));
		}
		return result;
	}

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

	public int foreignKeysSize() {
		return this.getForeignKeys().size();
	}


	// ***** foreignKeyColumns

	private synchronized Set<Column> getForeignKeyColumns() {
		if (this.foreignKeyColumns == null) {
			this.foreignKeyColumns = this.buildForeignKeyColumns();
		}
		return this.foreignKeyColumns;
	}

	private Set<Column> buildForeignKeyColumns() {
		if ( ! (this.dtpTable instanceof BaseTable)) {
			return Collections.emptySet();
		}
		Set<Column> result = new HashSet<Column>(this.columnsSize());
		for (Iterator<ForeignKey> stream = this.foreignKeys(); stream.hasNext(); ) {
			CollectionTools.addAll(result, stream.next().baseColumns());
		}
		return result;
	}

	public Iterator<Column> foreignKeyColumns() {
		return this.getForeignKeyColumns().iterator();
	}

	public int foreignKeyColumnsSize() {
		return this.getForeignKeyColumns().size();
	}

	public boolean foreignKeyColumnsContains(Column column) {
		return this.getForeignKeyColumns().contains(column);
	}

	// ********** Comparable implementation **********

	public int compareTo( Table table) {
		return Collator.getInstance().compare( this.getName(), table.getName());
	}
}
