package iitb.con.query;

import iitb.con.core.EntityInstance;
import iitb.con.core.Instance;
import iitb.con.core.RelationInstance;
import iitb.con.core.Type;
import iitb.con.ds.InstanceMetaItem;

import java.io.IOException;
import java.util.List;

/**
 * @author Prathab K
 *
 */
public interface Query {
    
    //Type or Instance Id Retrieval
    
    /**
     * Returns the type id of the specified instance
     * @param instanceId instance id
     * @return type id
     */
    public short getTypeId(int instanceId);
    
    /**
     * Returns the type id of the specified type name
     * @param typeName type name
     * @return type id
     */
    public short getTypeId(String typeName);
    
    /**
     * Returns the type name for the specified type id
     * @param typeId Type id
     * @return type name
     * @see Type
     */
    public String getTypeName(short typeId);
    
    /**
     * Returns all type ids
     * @return type ids as list
     */
    public List<Short> getAllTypeIds();
    
    /**
     * Returns all entity type ids
     * @return type ids as list
     */
    public List<Short> getAllEntityTypeIds();
    
    /**
     * Returns all relation type ids
     * @return type ids as list
     */
    public List<Short> getAllRelationTypeIds();
    
    /**
     * Returns the instance ids for the specified <tt>Type</tt> id
     * @param typeId type id
     * @return instance ids of the relevant type
     */
    public List<Integer> getInstanceIds(short typeId);
    
    /**
     * Returns the instance ids for the specified <tt>Type</tt> name
     * @param typeName type name
     * @return instance ids of the relevant type
     */
    public List<Integer> getInstanceIds(String typeName);
    
    /**
     * Returns the existing <code>Instance</code> ids from 
     * the concept-nets.<br>
     * The instance id is retrieved based on the type with the
     * specified attribute name and its value. <br>
     * Returns <code>NULL</code>, if <code>Instance</code> does not exists.
     * @param typeName type name
     * @param attributeName instance's attribute name
     * @param value the attribute value
     * @return instance ids as  list
     */
    public <K extends Comparable<K>> List<Integer> getInstanceIds(String typeName, 
            String attributeName, K value);
    
    
    /**
     * Returns the left associated entity id of the given relation id
     * @param relationInstanceId relation instance id
     * @return entity instance id
     */
    public int getLeftEntityId(int relationInstanceId);
    
    /**
     * Returns the right associated entity id of the given relation id
     * @param relationInstanceId relation instance id
     * @return entity instance id
     */
    public int getRightEntityId(int relationInstanceId);
    
    /**
     * Returns the instance ids based on the relation association of the specified instance
     * @param instanceId entity instance id
     * @return entity instance ids which have relations with the specified instance
     */
    public List<Integer> getRelatedInstanceIds(int instanceId);
    
    /**
     * Returns the related Instance ids for the specified entity instance id and 
     * filtered by relation type name
     * @param instanceId entity instance id whose relations are to be fetched
     * @param relationTypeName relation type name to filter the instance's relations
     * @return Instance's relations Id as <tt>Integer List</tt> 
     */
    public List<Integer> getRelatedInstanceIds(int instanceId, String relationTypeName);
    
    /**
     * Returns the associated relations Ids of an entity instance id
     * @param instanceId entity instance id whose relations are to be fetched
     * @return Instance's relations Id as <tt>Integer List</tt> 
     */
    public List<Integer> getRelationIds(int instanceId);
    
    /**
     * Returns the associated relations Ids of an entity instance id and
     * filtered by relation type name
     * @param instanceId entity instance id whose relations are to be fetched
     * @param relationTypeName relation type name to filter the instance's relations
     * @return Instance's relations Id as <tt>Integer List</tt> 
     */
    public List<Integer> getRelationIds(int instanceId, String relationTypeName);
    
    /**
     * Returns all the Entity and Relation Instances Id
     * @return Instance Ids as <tt>List</tt>
     */
    public List<Integer> getAllInstanceIds();
    
    /**
     * Returns all the Entity Instances Id
     * @return Instance Ids as <tt>List</tt>
     */
    public List<Integer> getAllEntityInstanceIds();
    
    /**
     * Returns all the Relation Instances Id
     * @return Instance Ids as <tt>List</tt>
     */
    public List<Integer> getAllRelationInstanceIds();
    
    //Type retrieval
    
    /**
     * Returns <tt>Type<tt> for the specified type name
     * @return {@link Type}
     */
    public Type getType(String typeName);
    
    //Instance retrieval
    
    /**
     * Returns the instance for the specified instance id
     * @param instanceId instance id
     * @return @link{Instance}
     */
    public Instance getInstance(int instanceId);
    
    
    /**
     * Returns the existing <code>Instance</code> from 
     * the concept-nets.<br>
     * The instance is retrieved based on the type with the
     * specified attribute name and its value. <br>
     * Returns <code>NULL</code>, if <code>Instance</code> does not exists.
     * @param typeName type name
     * @param attributeName instance's attribute name
     * @param value the attribute value
     * @return {@link iitb.con.core.Instance} list
     */
    public <K extends Comparable<K>> List<Instance> getInstances(String typeName, 
            String attributeName, K value);
    
    /**
     * Returns the instances for the specified instance id
     * @param instanceIds list of instance ids
     * @return @link{Instance}
     */
    public List<Instance> getInstances(List<Integer> instanceIds);
    
    /**
     * Returns all the instances for the specified <tt>Type</tt> 
     * @param typeId type id
     * @return instance list of the given type
     * @see Instance
     */
    public List<Instance> getInstances(Short typeId);
    
    /**
     * Returns all the instances for the specified <tt>Type</tt> 
     * @param typeName type name
     * @return instance list of the given type
     * @see Instance
     */
    public List<Instance> getInstances(String typeName);
    
    /**
     * Returns all the entity instances of specified <tt>Type</tt>
     * @param typeId type id
     * @return Entity instance list of the given type
     * @see EntityInstance
     */
    public List<EntityInstance> getEntityInstances(Short typeId);
    
    /**
     * Returns all the entity instances of specified <tt>Type</tt>
     * @param typeName type name
     * @return Entity instance list of the given type
     * @see EntityInstance
     */
    public List<EntityInstance> getEntityInstances(String typeName);
    
    /**
     * Returns all the relation instances of specified <tt>Type</tt>
     * @param typeId type id
     * @return Relation instance list of the given type
     * @see RelationInstance
     */
    public List<RelationInstance> getRelationInstances(Short typeId);
    
    /**
     * Returns all the relation instances of specified <tt>Type</tt>
     * @param typeName type name
     * @return Relation instance list of the given type
     * @see RelationInstance
     */
    public List<RelationInstance> getRelationInstances(String typeName);
    
    /**
     * Returns all the <tt>EntitiyInstances</tt> in the concept-net 
     * @return entity instance list
     * @see EntityInstance
     */
    public List<EntityInstance> getAllEntityInstances();
    
    /**
     * Returns all the <tt>RelationInstances</tt> in the concept-net 
     * @return relation instance list
     * @see RelationInstance
     */
    public List<RelationInstance> getAllRelationInstances();
    
    //for low-level access
    /**
     * Returns the instance meta item of the specified instance id
     * @param instanceId instance id
     * @return {@link InstanceMetaItem}
     */
    public InstanceMetaItem getInstanceMetaItem(int instanceId);
    
    //non query methods
    /**
     * Closes the files that associated with the query object
     * @throws IOException if file operation fails
     */
    public void close() throws IOException;

}