/*
Tiamat - a role-playing game framework
Item.java - representation of an item
 
 Copyright  (C) 2004-2005 Hugues Johnson
 
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
 
This program 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. See
the GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package com.huguesjohnson.tiamat;

import com.huguesjohnson.ImageLoader;
import com.huguesjohnson.PathResolver;
import com.huguesjohnson.serialization.Formatter;
import com.huguesjohnson.serialization.Storable;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;

/** Item - representation of an item
 * @author Hugues Johnson
 */
public class Item extends NamedObject implements Storable{

/* begin public constants */
    /** default value for equipped property */
    public final static boolean DEFAULT_EQUIPPED=false;
    /** default value for equipable property */
    public final static boolean DEFAULT_EQUIPABLE=false;
    /** default value for disappearOnUse property */
    public final static boolean DEFAULT_DISAPPEAR_ON_USE=false;
/* end public constants */
   
/* begin public properties */
    //relative path to full-size image for this Item, setting this reloads the actual image
    private String fullImagePath;
    /**
     * Sets the relative path to full-size image for this Item, setting this reloads the actual image.
     * @param fullImagePath The relative path to full-size image for this Item.
     */
    public void setFullImagePath(String fullImagePath){ 
        this.fullImagePath=fullImagePath; 
        this.fullImage=ImageLoader.loadBufferedImage(this.getFullImagePathAbsolute());
    }
    /**
     * Returns the relative path to full-size image for this Item.
     * @return The relative path to full-size image for this Item.
     */
    public String getFullImagePath(){ return(this.fullImagePath); }
    /**
     * Returns the absolute path to full-size image for this Item.
     * @return The absolute path to full-size image for this Item.
     */
    public String getFullImagePathAbsolute(){ return(PathResolver.getAbsolutePath(this.absoluteDir,this.fullImagePath)); }
    //full-size image for this item, change by setting fullImagePath
    private transient BufferedImage fullImage;
    /**
     * Returns the full-size image for this item, change by setting fullImagePath.
     * @return The full-size image for this item.
     */
    public BufferedImage getFullImage(){ return(this.fullImage); }
    //thumbnail image for this item, what would appear in a menu or dialog, change by setting thumbnailImagePath
    private transient BufferedImage thumbnailImage;
    /**
     * Returns the thumbnail image for this Item, what would appear in a menu or dialog, change by setting thumbnailImagePath.
     * @return The thumbnail image for this Item.
     */
    public BufferedImage getThumbnailImage(){ return(this.thumbnailImage); }
    //path to thumbnail image for this Item, what would appear in a menu or dialog, setting this reloads the actual image
    private String thumbnailImagePath;
    /**
     * Sets the relative path to thumbnail image for this Item, what would appear in a menu or dialog, setting this reloads the actual image.
     * @param thumbnailImagePath The relative path to thumbnail image for this Item, setting this reloads the actual image
     */
    public void setThumbnailImagePath(String thumbnailImagePath){ 
        this.thumbnailImagePath=thumbnailImagePath; 
        this.thumbnailImage=ImageLoader.loadBufferedImage(this.getThumbnailImagePathAbsolute());
    }
    /**
     * Returns the relative path to thumbnail image for this Item.
     * @return The relative path to thumbnail image for this Item.
     */
    public String getThumbnailImagePath(){ return(this.thumbnailImagePath); }
    /**
     * Returns the absolute path to thumbnail image for this Item.
     * @return The absolute path to thumbnail image for this Item.
     */
    public String getThumbnailImagePathAbsolute(){ return(PathResolver.getAbsolutePath(this.absoluteDir,this.thumbnailImagePath)); }
    //which attributes does this item modify
    private ArrayList<Target> targets;
    /**
     * Set the Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     * @param targets The Targets for this Item.
     */
    public void setTargets(Target[] targets){
		int length=targets.length;
		this.targets=new ArrayList<Target>(length);
        for(int index=0;index<length;index++){
            this.targets.add(index,targets[index]);
        }
    }
    /**
     * Returns the Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     * @return The Targets for this Item.
     */
    public Target[] getTargets(){ return(this.targets.toArray(new Target[0])); }
    /**
     * Sets the Target at the specified index.
     * @param index The index to set at.
     * @param target The Target to set.
     */
    public void setTarget(int index,Target target){ if((index>=0)&&(index<this.targets.size())){ this.targets.set(index,target); } }
    /**
     * Returns the Target at the specified index.
     * @param index The index to retrieve.
     * @return The Target at the specified index, null if index is out of range.
     */
    public Target getTarget(int index){
        if((index>=0)&&(index<this.targets.size())){
            return(this.targets.get(index)); 
        } 
        return(null); 
    }
    //whether or not this item is currently equipped
    private boolean equipped;
    /**
     * Sets whether this Item is currently equipped.
     * @param equipped Whether this Item is currently equipped.
     */
    public void setEquipped(boolean equipped){ this.equipped=equipped; }
    /**
     * Returns whether this Item is currently equipped.
     * @return True if the Item is equipped, false if it is not.
     */
    public boolean getEquipped(){ return(this.equipped); }
    //whether or not this item can be equipped
    private boolean equipable;
    /**
     * Sets whether this Item can be equipped.
     * @param equipable Whether this Item can be equipped.
     */
    public void setEquipable(boolean equipable){ this.equipable=equipable; }
    /**
     * Returns whether this Item can be equipped.
     * @return True if the Item can be equipped, false if it can not.
     */
    public boolean getEquipable(){ return(this.equipable); }
    //whether or not this item should disappear after being used
    private boolean disappearOnUse;
    /**
     * Sets whether this Item should disappear after being used.
     * @param disappearOnUse Whether this Item should disappear after being used.
     */
    public void setDisappearOnUse(boolean disappearOnUse){ this.disappearOnUse=disappearOnUse; }
    /**
     * Returns whether this Item should disappear after being used.
     * @return True if the Item should disappear after being used.
     */
    public boolean getDisappearOnUse(){ return(this.disappearOnUse); }
    //absolute path to the directory where images are stored
    private transient String absoluteDir;
    /** 
     * Sets the absolute working directory for files.
     * @param absoluteDir The full path to the working directory.
     */
    public void setAbsoluteDir(String absoluteDir){
        if(absoluteDir.endsWith(File.separator)){
            this.absoluteDir=absoluteDir;
        } else{
            this.absoluteDir=absoluteDir+File.separator;
        }
    }
/* end public properties */
    
/* begin constructors */
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     */
    public Item(String name,String description){
        super(name,description);
        this.fullImage=null;
        this.thumbnailImage=null;
        this.fullImagePath=new String();
        this.thumbnailImagePath=new String();
        this.targets=new ArrayList<Target>();
        this.equipped=Item.DEFAULT_EQUIPPED;
        this.equipable=Item.DEFAULT_EQUIPABLE;
        this.disappearOnUse=Item.DEFAULT_DISAPPEAR_ON_USE;
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param targets The Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     */
    public Item(String name,String description,Target[] targets){
        super(name,description);
        this.fullImage=null;
        this.thumbnailImage=null;
        this.fullImagePath=new String();
        this.thumbnailImagePath=new String();
        this.setTargets(targets);
        this.equipped=Item.DEFAULT_EQUIPPED;
        this.equipable=Item.DEFAULT_EQUIPABLE;
        this.disappearOnUse=Item.DEFAULT_DISAPPEAR_ON_USE;
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param targets The Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     * @param equipable Whether this Item can be equipped.
     */
    public Item(String name,String description,Target[] targets,boolean equipable){
        super(name,description);
        this.fullImage=null;
        this.thumbnailImage=null;
        this.fullImagePath=new String();
        this.thumbnailImagePath=new String();
        this.setTargets(targets);
        this.equipped=Item.DEFAULT_EQUIPPED;
        this.equipable=equipable;
        this.disappearOnUse=Item.DEFAULT_DISAPPEAR_ON_USE;
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param targets The Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     * @param equipable Whether this Item can be equipped.
     * @param disappearOnUse Whether this Item should disappear after being used.
     */
    public Item(String name,String description,Target[] targets,boolean equipable,boolean disappearOnUse){
        super(name,description);
        this.fullImage=null;
        this.thumbnailImage=null;
        this.fullImagePath=new String();
        this.thumbnailImagePath=new String();
        this.setTargets(targets);
        this.equipped=Item.DEFAULT_EQUIPPED;
        this.equipable=equipable;
        this.disappearOnUse=disappearOnUse;    
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param targets The Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     * @param equipable Whether this Item can be equipped.
     * @param disappearOnUse Whether this Item should disappear after being used.
     * @param equipped Whether this Item is equipped.
     */
    public Item(String name,String description,Target[] targets,boolean equipable,boolean disappearOnUse,boolean equipped){
        super(name,description);
        this.fullImage=null;
        this.thumbnailImage=null;
        this.fullImagePath=new String();
        this.thumbnailImagePath=new String();
        this.setTargets(targets);
        this.equipped=equipped;
        this.equipable=equipable;
        this.disappearOnUse=disappearOnUse;    
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param absoluteDir The full path to the working directory.
     * @param targets The Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     * @param equipable Whether this Item can be equipped.
     * @param disappearOnUse Whether this Item should disappear after being used.
     * @param equipped Whether this Item is equipped.
     */
    public Item(String name,String description,String absoluteDir,String fullImagePath,String thumbnailImagePath,Target[] targets,boolean equipable,boolean disappearOnUse,boolean equipped){
        super(name,description);
        this.setAbsoluteDir(absoluteDir);
        this.setFullImagePath(fullImagePath);
        this.setThumbnailImagePath(thumbnailImagePath);
        this.setTargets(targets);
        this.equipped=equipped;
        this.equipable=equipable;
        this.disappearOnUse=disappearOnUse;    
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param absoluteDir The full path to the working directory.
     * @param fullImagePath The relative path to full-size image for this Item.
     * @param thumbnailImagePath The relative path to thumbnail image for this Item.
     */
    public Item(String name,String description,String absoluteDir,String fullImagePath,String thumbnailImagePath){
        super(name,description);
        this.setAbsoluteDir(absoluteDir);
        this.setFullImagePath(fullImagePath);
        this.setFullImagePath(fullImagePath);
        this.setThumbnailImagePath(thumbnailImagePath);
        this.targets=new ArrayList<Target>();
        this.equipped=Item.DEFAULT_EQUIPPED;
        this.equipable=Item.DEFAULT_EQUIPABLE;
        this.disappearOnUse=Item.DEFAULT_DISAPPEAR_ON_USE;
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param absoluteDir The full path to the working directory.
     * @param fullImagePath The relative path to full-size image for this Item.
     * @param thumbnailImagePath The relative path to thumbnail image for this Item.
     * @param targets The Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     */
    public Item(String name,String description,String absoluteDir,String fullImagePath,String thumbnailImagePath,Target[] targets){
        super(name,description);
        this.setAbsoluteDir(absoluteDir);
        this.setFullImagePath(fullImagePath);
        this.setThumbnailImagePath(thumbnailImagePath);
        this.setTargets(targets);
        this.equipped=Item.DEFAULT_EQUIPPED;
        this.equipable=Item.DEFAULT_EQUIPABLE;
        this.disappearOnUse=Item.DEFAULT_DISAPPEAR_ON_USE;    
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param absoluteDir The full path to the working directory.
     * @param fullImagePath The relative path to full-size image for this Item.
     * @param thumbnailImagePath The relative path to thumbnail image for this Item.
     * @param targets The Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     * @param equipable Whether this Item can be equipped.
     */
    public Item(String name,String description,String absoluteDir,String fullImagePath,String thumbnailImagePath,Target[] targets,boolean equipable){
        super(name,description);
        this.setAbsoluteDir(absoluteDir);
        this.setFullImagePath(fullImagePath);
        this.setThumbnailImagePath(thumbnailImagePath);
        this.setTargets(targets);
        this.equipped=Item.DEFAULT_EQUIPPED;
        this.equipable=equipable;
        this.disappearOnUse=Item.DEFAULT_DISAPPEAR_ON_USE;    
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param absoluteDir The full path to the working directory.
     * @param fullImagePath The relative path to full-size image for this Item.
     * @param thumbnailImagePath The relative path to thumbnail image for this Item.
     * @param targets The Targets for this Item. For an Item, a Target is an Attribute that the Item modifies.
     * @param equipable Whether this Item can be equipped.
     * @param disappearOnUse Whether this Item should disappear after being used.
     */
    public Item(String name,String description,String absoluteDir,String fullImagePath,String thumbnailImagePath,Target[] targets,boolean equipable,boolean disappearOnUse){
        super(name,description);
        this.setAbsoluteDir(absoluteDir);
        this.setFullImagePath(fullImagePath);
        this.setThumbnailImagePath(thumbnailImagePath);
        this.setTargets(targets);
        this.equipped=Item.DEFAULT_EQUIPPED;
        this.equipable=equipable;
        this.disappearOnUse=disappearOnUse;
    }
    /**
     * Creates a new instance of Item.
     * @param name The name of this Item.
     * @param description The description of this Item.
     * @param absoluteDir The full path to the working directory.
     * @param fullImagePath The relative path to full-size image for this Item.
     * @param thumbnailImagePath The relative path to thumbnail image for this Item.
     * @param equipable Whether this Item can be equipped.
     * @param disappearOnUse Whether this Item should disappear after being used.
     * @param equipped Whether this Item is equipped.
     */
    public Item(String name,String description,String absoluteDir,String fullImagePath,String thumbnailImagePath,boolean equipable,boolean disappearOnUse,boolean equipped){
        super(name,description);
        this.setAbsoluteDir(absoluteDir);
        this.setFullImagePath(fullImagePath);
        this.setThumbnailImagePath(thumbnailImagePath);
        this.targets=new ArrayList<Target>();
        this.equipped=equipped;
        this.equipable=equipable;
        this.disappearOnUse=disappearOnUse;    
    }
/* end constructors */

/* begin public methods */
    /** Returns a string representation of the object.
     * @return A string representation of the object.
     */
    public String toString(){
        StringBuffer tostring=new StringBuffer(this.getClass().getName());
        tostring.append("\n  name="+this.getName());
        tostring.append("\n  description="+this.getDescription());
        tostring.append("\n  fullImagePath="+this.fullImagePath);
        tostring.append("\n  thumbnailImagePath="+this.thumbnailImagePath);
        tostring.append("\n  equipped="+this.equipped);
        tostring.append("\n  equipable="+this.equipable);
        tostring.append("\n  disappearOnUse="+this.disappearOnUse);
        tostring.append("\n  targets=");
        int size=this.targets.size();
        tostring.append("\n    size="+size);
        for(int index=0;index<size;index++){
            tostring.append("\n    targets["+index+"]="+this.targets.get(index).toString());
        }
        return(tostring.toString());
    }
    /** Returns the number of targets for this item. 
     * @return The number of targets for this item.
     */
    public int getTargetCount(){ 
        return(this.targets.size()); 
    }
    /** Adds a Target to the collection of Targets 
     * @param target The Target to add.
     */
    public void addTarget(Target target){
        this.targets.add(target);
    }
    /** The onDeserialize event should be fired after an object is de-serialized.
     * This allows objects to load transient members, set their working directory, and load Storable members if needed.
     * @param formatter the formatter to use to load any storable members
     * @param absoluteDir the working directory since all paths stored in the object should be relative
     */
    public void onDeserialize(Formatter formatter,String absoluteDir){
        this.setAbsoluteDir(absoluteDir);
        this.fullImage=ImageLoader.loadBufferedImage(this.fullImagePath);
        this.thumbnailImage=ImageLoader.loadBufferedImage(this.thumbnailImagePath);
    }
/* end public methods */
}