package hiro.yoshioka.sql.resource.view;

import hiro.yoshioka.sql.resource.DBSequence;
import hiro.yoshioka.sql.resource.IDBColumn;
import hiro.yoshioka.sql.resource.IDBResource;
import hiro.yoshioka.sql.resource.IDBSchema;
import hiro.yoshioka.sql.resource.IDBSequence;
import hiro.yoshioka.sql.resource.IDBTable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jface.viewers.IStructuredSelection;

public class DBResourceTreeSelection {
	IStructuredSelection selection;
	boolean hasMultiTypeResource;
	Set<IDBSchema> fDBSchemaList;
	Set<IDBTable> fDBTableList;
	Set<IDBColumn> fDBColumnList;
	Set<IDBSequence> fDBSequenceList;
	IDBResource firstDBResource;

	public DBResourceTreeSelection(IStructuredSelection selection) {
		this.selection = selection;
		for (Iterator ite = selection.iterator(); ite.hasNext();) {
			Object o = ite.next();
			if (o instanceof IDBResource && this.firstDBResource == null) {
				firstDBResource = (IDBResource) o;
			}
			if (o instanceof IDBSchema) {
				if (fDBSchemaList == null) {
					fDBSchemaList = new LinkedHashSet<IDBSchema>();
				}
				fDBSchemaList.add((IDBSchema) o);
			} else if (o instanceof IDBTable) {
				if (fDBTableList == null) {
					fDBTableList = new LinkedHashSet<IDBTable>();
				}
				fDBTableList.add((IDBTable) o);
			} else if (o instanceof IDBColumn) {
				if (fDBColumnList == null) {
					fDBColumnList = new LinkedHashSet<IDBColumn>();
				}
				fDBColumnList.add((IDBColumn) o);
			} else if (o instanceof DBSequence) {
				if (fDBSequenceList == null) {
					fDBSequenceList = new LinkedHashSet<IDBSequence>();
				}
				fDBSequenceList.add((DBSequence) o);
			}
		}
		if (fDBSchemaList != null) {
			if (fDBTableList != null || fDBColumnList != null
					|| fDBSequenceList != null) {
				hasMultiTypeResource = true;
			}
		} else if (fDBTableList != null) {
			if (fDBSchemaList != null || fDBColumnList != null
					|| fDBSequenceList != null) {
				hasMultiTypeResource = true;
			}
		} else if (fDBColumnList != null) {
			if (fDBSchemaList != null || fDBTableList != null
					|| fDBSequenceList != null) {
				hasMultiTypeResource = true;
			}
		}
	}

	public IDBResource getFirstDBResource() {
		return this.firstDBResource;
	}

	public List getFirstDBResourceTreeList() {
		List retList = new ArrayList();
		IDBResource r = this.firstDBResource;
		while (r != null) {
			retList.add(0, r);
			r = r.getParent();
		}
		return retList;
	}

	public int sizeTotal() {
		return fDBSchemaList.size() + fDBTableList.size()
				+ fDBColumnList.size() + fDBSequenceList.size();
	}

	public boolean hasMultiResource() {
		return hasMultiTypeResource;
	}

	public boolean hasSchema() {
		return fDBSchemaList != null;
	}

	public IDBSchema getNoChildSchema() {
		if (fDBSchemaList == null) {
			return null;
		}
		for (IDBSchema schema : fDBSchemaList) {
			if (schema.getTableOrViews().length == 0) {
				return schema;
			}
		}
		return null;
	}

	public boolean hasTable() {
		if (fDBTableList == null) {
			return false;
		}
		for (IDBTable table : fDBTableList) {
			if (table.isTable()) {
				return true;
			}
		}
		return false;
	}

	public boolean hasView() {
		if (fDBTableList == null) {
			return false;
		}
		for (IDBTable table : fDBTableList) {
			if (table.isView()) {
				return true;
			}
		}
		return false;
	}

	public boolean hasSequence() {
		return fDBSequenceList != null;
	}

	public Set<IDBSequence> getSequenceSet() {
		return getSequenceSet(false);
	}

	public Set<IDBSequence> getSequenceSet(boolean theOtherResourcesExpand) {
		if (theOtherResourcesExpand) {
			Set<IDBSequence> retList = new LinkedHashSet<IDBSequence>();

			if (fDBSchemaList != null) {
				for (IDBSchema schema : fDBSchemaList) {
					retList.addAll(Arrays.asList(schema.getSequences()));
				}
			}
			retList.addAll(fDBSequenceList);
			return retList;
		} else {
			if (fDBSequenceList == null) {
				return Collections.EMPTY_SET;
			}
			return fDBSequenceList;
		}
	}

	public Set<IDBTable> getTableAndViewSet(boolean theOtherResourcesExpand) {
		if (theOtherResourcesExpand) {
			Set<IDBTable> retList = new LinkedHashSet<IDBTable>();

			if (fDBSchemaList != null) {
				for (IDBSchema schema : fDBSchemaList) {
					retList.addAll(Arrays.asList(schema.getTableOrViews()));
				}
			}
			if (fDBTableList != null) {
				retList.addAll(fDBTableList);
			}
			return retList;
		} else {
			if (fDBTableList == null) {
				return Collections.EMPTY_SET;
			}
			return fDBTableList;
		}
	}

	public Set<IDBSchema> getSchemaSet(boolean theOtherResourcesExpand) {
		if (theOtherResourcesExpand) {
			Set<IDBSchema> retList = new LinkedHashSet<IDBSchema>();

			if (fDBTableList != null) {
				for (IDBTable table : fDBTableList) {
					IDBResource p = table.getParent();
					if (p instanceof IDBSchema) {
						retList.add((IDBSchema) p);
					}
				}
			}
			if (fDBSchemaList != null) {
				retList.addAll(fDBSchemaList);
			}
			return retList;
		} else {
			if (fDBSchemaList == null) {
				return Collections.EMPTY_SET;
			}
			return fDBSchemaList;
		}
	}

}