/*
Tiamat - a role-playing game framework
GameDataManager.java - manages global data for a game
    
 Copyright  (C) 2006 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 java.io.File;

import com.huguesjohnson.PathResolver;
import com.huguesjohnson.serialization.Formatter;
import com.huguesjohnson.serialization.Storable;
import com.huguesjohnson.serialization.StorageException;
import com.huguesjohnson.tiamat.graphics.Sequence;

/** 
 * GameDataManager.java - manages global data for a game
 * @author Hugues Johnson
 */
public class GameDataManager implements Storable{
//begin public properties
    /** 
     * Absolute path to the directory where objects are saved. 
     */
    protected transient String absoluteDir;
    /** 
     * Sets the absolute path to the directory where objects are saved.
     * @param absoluteDir The absolute path to the directory where characters are saved.
     */
    public void setAbsoluteDir(String absoluteDir){
        if(absoluteDir.endsWith(File.separator)){
            this.absoluteDir=absoluteDir;
        } else{
            this.absoluteDir=absoluteDir+File.separator;
        }
    }
//end public properties
	
//begin private members
    //table containing names and paths to saved character files, relative to absoluteDir
    private StringTable characterPaths; 
    //table containing names and paths to saved item files, relative to absoluteDir    
    private StringTable itemPaths; 
    //table containing names and paths to saved location files, relative to absoluteDir
    private StringTable locationPaths;
    //table containing names and paths to saved sequence files, relative to absoluteDir
    private StringTable sequencePaths;
    //used for string table lookups
    private final static transient String DEFAULT_VALUE=":?*"; //shouldn't be a valid file name in any OS
//end public members
	
//begin constructors
    /**
     * Creates a new instance of GameDataManager. 
     */
    public GameDataManager(){ 
    	this.characterPaths=new StringTable();
    	this.itemPaths=new StringTable();
    	this.locationPaths=new StringTable();
    	this.sequencePaths=new StringTable();
    }
//end constructors
	
//begin public methods	
    /** 
     * Add a Character to the game data.
     * @param name The name of the Character to add.
     * @param absoluteCharacterPath The absolute path to the Character file.
     */
    public void addCharacter(String name,String absoluteCharacterPath){
    	String relativePath=PathResolver.getRelativePath(this.absoluteDir,absoluteCharacterPath);
    	this.characterPaths.set(name,relativePath);
    }
    /** 
     * Retrieve (deserialize) a Character by name.
     * @param name The name of the Character to retrieve.
     * @param formatter The formatter to use to load the Character.
     * @return A concrete Character.
     */
    public Character getCharacter(String name,Formatter formatter){
    	Character character=null;
    	String relativePath=this.characterPaths.get(name,DEFAULT_VALUE);
    	if(!relativePath.equals(DEFAULT_VALUE)){
    		String absolutePath=PathResolver.getAbsolutePath(this.absoluteDir,relativePath);
    		try{
    			character=CharacterFactory.load(absolutePath,formatter);
    		} catch(UnsupportedCharacterException ucx){
    			ucx.printStackTrace();
    		}
    	}
    	return(character);
    }
    /** 
     * Save (serialize) a character.
     * @param name The name of the Character to save.
     * @param character The actual Character object to save.
     * @param formatter The formatter to use to save the Character.
     */
    public void saveCharacter(String name,Character character,Formatter formatter){
    	String relativePath=this.characterPaths.get(name,DEFAULT_VALUE);
    	String absolutePath;
    	if(!relativePath.equals(DEFAULT_VALUE)){
    		absolutePath=PathResolver.getAbsolutePath(this.absoluteDir,relativePath);
    	} else{
    		absolutePath=this.absoluteDir+name+".character.xml";
        	this.characterPaths.set(this.absoluteDir,PathResolver.getRelativePath(this.absoluteDir,absolutePath));
    	}
    	try{
    		formatter.saveTo(character,absolutePath);
    	} catch(StorageException x){
    		x.printStackTrace();
    	}
    }
    /** 
     * Add an Item to the game data.
     * @param name The name of the Item to add.
     * @param absoluteItemPath The absolute path to the Item file.
     */
    public void addItem(String name,String absoluteItemPath){
    	String relativePath=PathResolver.getRelativePath(this.absoluteDir,absoluteItemPath);
    	this.itemPaths.set(name,relativePath);
    }
    /** 
     * Retrieve an Item by name.
     * @param name The name of the Item to retrieve.
     * @param formatter The formatter to use to load the Item.
     * @return A concrete Item.
     */
    public Item getItem(String name,Formatter formatter){
    	Item item=null;
    	String relativePath=this.itemPaths.get(name,DEFAULT_VALUE);
    	if(!relativePath.equals(DEFAULT_VALUE)){
    		String absolutePath=PathResolver.getAbsolutePath(this.absoluteDir,relativePath);
    		try{
    			item=(Item)formatter.loadFrom(relativePath);
    		} catch(StorageException sx){
    			sx.printStackTrace();
    		}
    	}
    	return(item);
    }
    /** 
     * Save (serialize) an Item.
     * @param name The name of the Item to save.
     * @param item The actual Item object to save.
     * @param formatter The formatter to use to save the Item.
     */
    public void saveItem(String name,Item item,Formatter formatter){
    	String relativePath=this.itemPaths.get(name,DEFAULT_VALUE);
    	String absolutePath;
    	if(!relativePath.equals(DEFAULT_VALUE)){
    		absolutePath=PathResolver.getAbsolutePath(this.absoluteDir,relativePath);
    	} else{
    		absolutePath=this.absoluteDir+name+".item.xml";
        	this.itemPaths.set(this.absoluteDir,PathResolver.getRelativePath(this.absoluteDir,absolutePath));
    	}
    	try{
    		formatter.saveTo(item,absolutePath);
    	} catch(StorageException x){
    		x.printStackTrace();
    	}
    }
    /** 
     * Add a Location to the game data.
     * @param name The name of the Location to add.
     * @param absoluteLocationPath The absolute path to the Location file.
     */
    public void addLocation(String name,String absoluteLocationPath){
    	String relativePath=PathResolver.getRelativePath(this.absoluteDir,absoluteLocationPath);
    	this.locationPaths.set(name,relativePath);
    }
    /** 
     * Retrieve a Location by name.
     * @param name The name of the Location to retrieve.
     * @param formatter The formatter to use to load the Location.
     * @return A concrete Location.
     */
    public Location getLocation(String name,Formatter formatter){
    	Location location=null;
    	String relativePath=this.locationPaths.get(name,DEFAULT_VALUE);
    	if(!relativePath.equals(DEFAULT_VALUE)){
    		String absolutePath=PathResolver.getAbsolutePath(this.absoluteDir,relativePath);
    		try{
    			location=(Location)formatter.loadFrom(relativePath);
    		} catch(StorageException sx){
    			sx.printStackTrace();
    		}
    	}
    	return(location);
    }
    /** 
     * Save (serialize) a Location.
     * @param name The name of the Location to save.
     * @param location The actual Location object to save.
     * @param formatter The formatter to use to save the Location.
     */
    public void saveLocation(String name,Location location,Formatter formatter){
    	String relativePath=this.locationPaths.get(name,DEFAULT_VALUE);
    	String absolutePath;
    	if(!relativePath.equals(DEFAULT_VALUE)){
    		absolutePath=PathResolver.getAbsolutePath(this.absoluteDir,relativePath);
    	} else{
    		absolutePath=this.absoluteDir+name+".location.xml";
        	this.locationPaths.set(this.absoluteDir,PathResolver.getRelativePath(this.absoluteDir,absolutePath));
    	}
    	try{
    		formatter.saveTo(location,absolutePath);
    	} catch(StorageException x){
    		x.printStackTrace();
    	}    
    }
    /** 
     * Add a Sequence to the game data.
     * @param name The name of the Sequence to add.
     * @param absoluteLocationPath The absolute path to the Sequence file.
     */
    public void addSequence(String name,String absoluteLocationPath){
    	String relativePath=PathResolver.getRelativePath(this.absoluteDir,absoluteLocationPath);
    	this.sequencePaths.set(name,relativePath);
    }
    /** 
     * Retrieve a Sequence by name.
     * @param name The name of the Sequence to retrieve.
     * @param formatter The formatter to use to load the Sequence.
     * @return A concrete Sequence.
     */
    public Sequence getSequence(String name,Formatter formatter){
    	Sequence sequence=null;
    	String relativePath=this.sequencePaths.get(name,DEFAULT_VALUE);
    	if(!relativePath.equals(DEFAULT_VALUE)){
    		String absolutePath=PathResolver.getAbsolutePath(this.absoluteDir,relativePath);
    		try{
    			sequence=(Sequence)formatter.loadFrom(relativePath);
    		} catch(StorageException sx){
    			sx.printStackTrace();
    		}
    	}
    	return(sequence);
    }
    /** 
     * Save (serialize) a Sequence.
     * @param name The name of the Sequence to save.
     * @param sequence The actual Sequence object to save.
     * @param formatter The formatter to use to save the Sequence.
     */
    public void saveSequence(String name,Sequence sequence,Formatter formatter){
    	String relativePath=this.sequencePaths.get(name,DEFAULT_VALUE);
    	String absolutePath;
    	if(!relativePath.equals(DEFAULT_VALUE)){
    		absolutePath=PathResolver.getAbsolutePath(this.absoluteDir,relativePath);
    	} else{
    		absolutePath=this.absoluteDir+name+".sequence.xml";
        	this.locationPaths.set(this.absoluteDir,PathResolver.getRelativePath(this.absoluteDir,absolutePath));
    	}
    	try{
    		formatter.saveTo(sequence,absolutePath);
    	} catch(StorageException x){
    		x.printStackTrace();
    	}    
    }
	/* (non-Javadoc)
	 * @see com.huguesjohnson.serialization.Storable#onDeserialize(com.huguesjohnson.serialization.Formatter, java.lang.String)
	 */
	public void onDeserialize(Formatter formatter,String absoluteDir){
        this.setAbsoluteDir(absoluteDir);
    	//prevent null pointer issue
        if(this.characterPaths==null){ this.characterPaths=new StringTable(); }
        if(this.itemPaths==null){ this.itemPaths=new StringTable(); }
        if(this.locationPaths==null){ this.locationPaths=new StringTable(); }
	}
//end public methods	
}