/*
Tiamat - a role-playing game framework
Character.java - abstract representation of a character
 
 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 com.huguesjohnson.tiamat.graphics.Sprite;
import java.awt.image.BufferedImage;
import java.io.File;

/** Character - abstract representation of a character
 * @author Hugues Johnson
 */
public abstract class Character implements Storable{
/* begin public properties */
    //relative path to full-size image for this Character, setting this reloads the actual image
    private String fullImagePath;
    /**
     * Sets the relative path to full-size image for this Character, setting this reloads the actual image.
     * @param fullImagePath The relative path to full-size image for this Character.
     */
    public void setFullImagePath(String fullImagePath){ 
        this.fullImagePath=fullImagePath; 
        this.fullImage=ImageLoader.loadBufferedImage(this.getFullImagePathAbsolute());
    }
    /**
     * Retuns the relative path to full-size image for this Character.
     * @return The relative path to full-size image for this Character.
     */
    public String getFullImagePath(){ return(this.fullImagePath); }
    /**
     * Retuns the absolute path to full-size image for this Character.
     * @return The absolute path to full-size image for this Character.
     */
    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, change by setting fullImagePath.
     */
    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, what would appear in a menu or dialog, change by setting thumbnailImagePath.
     */
    public BufferedImage getThumbnailImage(){ return(this.thumbnailImage); }
    //path to thumbnail image for this Character, 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 Character, what would appear in a menu or dialog, setting this reloads the actual image.
     * @param thumbnailImagePath The relative path to thumbnail image for this Character, what would appear in a menu or dialog, setting this reloads the actual image.
     */
    public void setThumbnailImagePath(String thumbnailImagePath){ 
        this.thumbnailImagePath=thumbnailImagePath; 
        this.thumbnailImage=ImageLoader.loadBufferedImage(this.getThumbnailImagePathAbsolute());
    }
    /**
     * Retuns the relative path to thumbnail image for this Character.
     * @return The relative path to thumbnail image for this Character.
     */
    public String getThumbnailImagePath(){ return(this.thumbnailImagePath); }
    /**
     * Retuns the absolute path to thumbnail image for this Character.
     * @return The absolute  path to thumbnail image for this Character.
     */
    public String getThumbnailImagePathAbsolute(){ return(PathResolver.getAbsolutePath(this.absoluteDir,this.thumbnailImagePath)); }
    //attributes such as strength, hit points, or experience points
    private AttributeCollection attributes;
    public AttributeCollection getAttributes(){ 
    	if(this.attributes==null){ this.attributes=new AttributeCollection(); }
    	return(this.attributes); 
    }
    public void setAttributes(AttributeCollection attributes){ this.attributes=attributes; }
    //items the character is carrying
    private ItemCollection items;
    /**
     * Returns the Items this Character is carrying.
     * @return The Items this Character is carrying.
     */
    public ItemCollection getItems(){ 
    	if(this.items==null){ this.items=new ItemCollection(); }
    	return(this.items); 
    }
    /** Sets the Items this Character is carrying.
     * @param items The new Items for this Character.
     */
    public void setItems(ItemCollection items){ this.items=items; }
    //skills the character possesses
    private SkillCollection skills;
    /**
     * Returns this Character's Skills.
     * @return This Character's Skills.
     */
    public SkillCollection getSkills(){ 
    	if(this.skills==null){ this.skills=new SkillCollection(); }
    	return(this.skills); 
    }
    /**
     * Sets this Character's Skills.
     * @param skills The new Skills for this Character.
     */
    public void setSkills(SkillCollection skills){ this.skills=skills; }
    //string values for a character such as names, class, or race
    private StringTable profile;
    /**
     * Returns the profile (i.e. name, class, or race) for this Character.
     * @return The profile (i.e. name, class, or race) for this Character.
     */
    public StringTable getProfile(){ 
    	if(this.profile==null){ this.profile=new StringTable(); }
    	return(this.profile); 
    }
    /**
     * Sets the profile (i.e. name, class, or race) for this Character.
     * @param profile The new profile (i.e. name, class, or race) for this Character.
     */
    public void setProfile(StringTable profile){ this.profile=profile; }
    //path to the public sprite's underlying file, setting this reloads the sprite
    private String spritePath;
    /**
     * Returns the relative path to this Character's Sprite.
     * @return The relative path to this Character's Sprite.
     */
    public String getSpritePath(){ return(this.spritePath); }
    /**
     * Returns the absolute path to this Character's Sprite.
     * @return The absolute path to this Character's Sprite.
     */
    public String getSpritePathAbsolute(){ return(PathResolver.getAbsolutePath(this.absoluteDir,this.spritePath)); }
    /**
     * Sets the path to the Sprite's underlying file, setting this reloads the Sprite.
     * @param spritePath The relative path to the Sprite's underlying file, setting this reloads the Sprite.
     * @param formatter The formatter used to deserialize this Sprite.
     */
    public void setSpritePath(String spritePath,Formatter formatter){
        try{
            if(spritePath!=null){
                this.sprite=(Sprite)formatter.loadFrom(PathResolver.getAbsolutePath(this.absoluteDir,spritePath));
            }
            this.spritePath=spritePath;
        } catch(Exception x){
            x.printStackTrace();
        }
    }
    //the physical sprite for the character, change by setting spritePath
    private transient Sprite sprite;
    /**
     * Returns the physical sprite for this Character, change by setting spritePath.
     * @return The physical sprite for this Character.
     */
    public Sprite getSprite(){ return(this.sprite); }
    //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 an empty Character */
    public Character(){ }
/* end constructors */
    
/* begin public methods */    
    /** 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.getFullImagePathAbsolute());
        this.thumbnailImage=ImageLoader.loadBufferedImage(this.getThumbnailImagePathAbsolute());
        //buffer images for items
        Item[] allItems=this.getItems().getAll();
        int length=allItems.length;
        for(int index=0;index<length;index++){
            allItems[index].onDeserialize(formatter,absoluteDir);
        }
        //load the sprite
        this.setSpritePath(this.getSpritePath(),formatter);
    }
/* end public methods */        
}