package com.quantum.view.bookmark;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.quantum.model.Column;
import com.quantum.model.Entity;
import com.quantum.model.EntityHolder;
import com.quantum.model.NotConnectedException;
import com.quantum.model.SchemaHolder;
import com.quantum.model.Table;
import com.quantum.model.View;

/**
 * @author BC
 */
public class EntityNode extends TreeNode implements EntityHolder {

    private Entity entity;
    private boolean longFormName;
    
    private List columns = Collections.synchronizedList(new ArrayList());
    private List foreignKeys = Collections.synchronizedList(new ArrayList());
    boolean initialized = false;
    
    public EntityNode(TreeNode parent, Entity entity) {
        this(parent, entity, false);
    }
    public EntityNode(TreeNode parent, Entity entity, boolean longFormName) {
        super(parent);
        this.entity = entity;
        this.longFormName = longFormName;
        
        if (parent instanceof SchemaHolder) {
            SchemaHolder schemaHolder = (SchemaHolder) parent;
            if (!schemaHolder.getSchema().getDisplayName().equals(entity.getSchema())) {
                this.longFormName = true;
            }
        }
    }

    public Object[] getChildren() throws NotConnectedException, SQLException {
    	 if (!isInitialized()) {
    	 	initializeChildren();
    	 }
    	
        if (this.children.size() > 0) {
            return (ColumnNode[]) this.children.toArray(new ColumnNode[this.children.size()]);
        } else {
            return BookmarkListNode.EMPTY_ARRAY;
        }
    }

    protected synchronized void initializeChildren() throws NotConnectedException, SQLException {
    	boolean wasInitialized = isInitialized();
        Map map = getChildrenAsMap();
        Column[] columns = this.entity.getColumns();
        this.children.clear();
        for (int i = 0, length = (columns == null) ? 0 : columns.length;
            i < length;
            i++) {
        	
        	ColumnNode node = (ColumnNode) map.get(columns[i].getName());
        	if (node == null) {
        		this.children.add(new ColumnNode(this, columns[i]));
        	} else {
        		node.setColumn(columns[i]);
        		this.children.add(node);
        	}
        	
        	if (wasInitialized) {
        		firePropertyChange("columns", null, null);
        	}
        }
    }
    
    private Map getChildrenAsMap() {
    	Map map = new HashMap();
    	for (Iterator i = this.children.iterator(); i.hasNext();) {
			TreeNode node = (TreeNode) i.next();
			map.put(node.getName(), node);
		}
    	return map;
    }

    public boolean hasChildren() {
        if (!isSequence()) {
            return true;
        } else {
            return false;
        }
    }
    
    public Entity getEntity() {
        return this.entity;
    }
    
    public String getName() {
        return this.entity.getName();
    }
    
    public String getLabelName() {
        return (this.longFormName) ? this.entity.getQualifiedName() : this.entity.getName();
    }
    
    public boolean isTable() {
        return Entity.TABLE_TYPE.equals(this.entity.getType());
    }

    public boolean isView() {
        return Entity.VIEW_TYPE.equals(this.entity.getType());
    }

    public boolean isSequence() {
        return Entity.SEQUENCE_TYPE.equals(this.entity.getType());
    }

    protected String getImageName() {
        if (isSequence()) {
            return "sequence.gif";
        } else if (isView()) {
            return "view.gif";
        } else {
            if (this.entity.exists() == null || this.entity.exists().booleanValue()){
            	if (this.entity.isSynonym())
            		return "big_syn_table.gif";
            	else
            		return "bigtable.gif";
            } else
            	return "missingtable.gif";
   
   
        }
    }

    public String getLabelDecorations(LabelDecorationInstructions instructions) {
        String decoration = null;
        if (instructions.isSizeVisible()) {
            Integer size = getSize();
            if (size != null) {
                decoration = ((decoration == null) ? "" : decoration) 
                    + "[" + size + "]";
            }
        }
        return decoration;
    }
    
    private Integer getSize() {
        if (isTable()) {
            return ((Table) this.entity).getSize();
        } else if (isView()) {
            return ((View) this.entity).getSize();
        } else {
            return null;
        }
    }
    
    public int compareTo(Object o) {
        if (o instanceof EntityNode) {
            EntityNode that = (EntityNode) o;
            return this.entity.getQualifiedName().compareTo(
                that.entity.getQualifiedName());
        } else {
            return super.compareTo(o);
        }
    }
	void setEntity(Entity entity) {
		this.entity = entity;
	}
}