/* Copyright (C) 2009  CSE,IIT Bombay  http://www.cse.iitb.ac.in

This file is part of the ConStore open source storage facility for concept-nets.

ConStore is free software and distributed under the 
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License;
you can copy, distribute and transmit the work
with the work attribution in the manner specified by the author or licensor.
You may not use this work for commercial purposes and may not alter, 
transform, or build upon this work.

Please refer the legal code of the license, available at
http://creativecommons.org/licenses/by-nc-nd/3.0/legalcode

ConStore is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  */

package iitb.con.core;

import iitb.con.util.Result;


/**
 * Relation is associated with two entities.<br>
 * Relation class provides methods to create and remove the
 * relations among the entities.<br>
 * The relation is created between two items, which is considered
 * as left-item and right-item. To remove any item, set <code>NULL</code>.<br>
 * 
 * @author Prathab K
 * @see Type
 * @see RelationInstance
 */
public class Relation extends Type {

    /** Relation's left role name */
    public String leftRole;

    /** Relation's right role name */
    public String rightRole;

    /** Relation's left entity id */
    private short leftEntityId;

    /** Relation's right entity id */
    private short rightEntityId;

    /** Relation direction from left item to right item */
    public static byte LEFT_TO_RIGHT = 0;

    /** Relation direction bidirectional for left- and right-item */
    public static byte BIDIRECTIONAL = 1;

    /** Relation direction kind */
    private byte direction = BIDIRECTIONAL; //default BIDIRECTIONAL

    public Relation() { }
    
    /**
     * Constructs the <code>Relation</code> with name
     * @param name relation name
     */
    public Relation(String name) {
        this.name = name;
    }

    /**
     * Constructs the <code>Relation</code> with name and roles
     * @param name relation name
     * @param leftRole left role name
     * @param rightRole right role name
     */
    public Relation(String name, String leftRole, String rightRole) {
        this.name = name;
        this.leftRole = leftRole;
        this.rightRole = rightRole;
    }
    
    /**
     * Returns the left entity id of the relation
     * @return the leftEntityId
     */
    public short getLeftEntityId() {
        return leftEntityId;
    }

    /**
     * Set the left entity id of the relation. 
     * The entity id should be greater than zero.
     * @param leftEntityId the leftEntityId to set
     * @return {@link Result}
     */
    public Result setLeftEntityId(short leftEntityId) {
        if(leftEntityId > 0) {
            this.leftEntityId = leftEntityId;
            return new Result(true);
        }
        return new Result(false, "'" + leftEntityId +"' Invalid Entity id");
        
    }

    /**
     * Returns the right entity id of the relation
     * @return the rightEntityId
     */
    public short getRightEntityId() {
        return rightEntityId;
    }

    /**
     * Set the right entity id of the relation. 
     * The entity id should be greater than zero.
     * @param rightEntityId the rightEntityId to set
     * @return {@link Result}
     */
    public Result setRightEntityId(short rightEntityId) {
        if(rightEntityId > 0) {
            this.rightEntityId = rightEntityId;
            return new Result(true);
        }
        return new Result(false, "'" + rightEntityId +"' Invalid Entity id");
    }

    /**
     * Sets the entity type for the left item.
     * Only the entity id is set.
     * @param entity {@link Entity}
     * @return {@link Result}
     */
    public Result setLeft(Entity entity) {
        if (entity == null) {
            this.leftEntityId = -1;
            return new Result(false, "EntityType is NULL");
        } else {
            if (entity.id < 0)
                return new Result(false, "Entity Id is NULL");
            else {
                this.leftEntityId = entity.id;
                return new Result(true);
            }
        }
    }

    /**
     * Sets the entity type for the right item.
     * Only the entity id is set.
     * @param entity {@link Entity}
     * @return {@link Result}
     */
    public Result setRight(Entity entity) {
        if (entity == null) {
            this.rightEntityId = -1;
            return new Result(false, "EntityType is NULL");
        } else {
            if (entity.id < 0)
                return new Result(false, "Entity Id is NULL");
            else {
                this.rightEntityId = entity.id;
                return new Result(true);
            }
        }
    }

    /**
     * Sets the direction kind of the Relation.
     * @param direction direction link
     * @return {@link Result}
     */
    public Result setDirection(byte direction) {
        if (direction < 0 && direction > 1)
            return new Result(false, "Invalid direction kind");
        else {
            this.direction = direction;
            return new Result(true);
        }
    }

    /**
     * Returns the left entity type in the relation.
     * @return {@link EntityType}
     * @deprecated
     */
    public Entity getLeftEntity() {
        //TODO: Using entity type id , fetch the entity
        return null;
    }

    /**
     * Returns the right entity type in the relation.
     * @return {@link EntityType}
     * @deprecated
     */
    public Entity getRightEntity() {
        //TODO: Using entity type id , fetch the entity
        return null;
    }

    /**
     * Returns the direction kind in the relation.<br>
     * 0 - LEFT_TO_RIGHT<br>
     * 1 - BIDIRECTIONAL<br>
     * @return byte - direction 
     */
    public byte getDirection() {
        return this.direction;
    }
    
    /**
     * Returns the direction kind in the relation as string.
     * @param direction relation's direction kind
     * @return relation's direction kind string
     */
    public static String getDirectionString(byte direction) {
        switch(direction) {
            case 0: return "LEFT_TO_RIGHT";
            case 1: return "BIDIRECTIONAL";
            default: return "";
        }
    }
}