/*
Tiamat - a role-playing game framework
Area.java - collection of layers and characters to represent an area
 
 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.PathResolver;
import com.huguesjohnson.serialization.Formatter;
import com.huguesjohnson.serialization.Storable;
import com.huguesjohnson.tiamat.graphics.Layer;
import java.io.File;
import java.util.ArrayList;

/** Area - collection of layers and characters to represent an area
 * @author Hugues Johnson
 */
public class Area implements Storable{
/* begin public properties */
     //the layers for this area
    private ArrayList<Layer> layers;
    /**
     * Sets the Layers for this Area.
     * @param layers The new Layers for this Area.
     */
    public void setLayers(Layer[] layers){
        int length=layers.length;
        this.layers=new ArrayList<Layer>(length);
        for(int index=0;index<length;index++){
            this.layers.add(index,layers[index]);
        }
    }
    /** 
     * Returns the Layers for this Area.
     * @return The Layers for this Area.
     */
    public Layer[] getLayers(){ return(this.layers.toArray(new Layer[0])); }
    /** 
     * Adds a Layer to this Area.
     * @param layer The Layer to add.
     */
    public void addLayer(Layer layer){ 
        layer.setAbsoluteDir(this.absoluteDir);
        this.layers.add(layer); 
    }
    //the characters in this area, change by setting character paths
    private transient ArrayList<Character> characters;
    /**
     * Returns the Characters in this Area.
     * @return The Characters in this Area.
     */
    public Character[] getCharacters(){ return(this.characters.toArray(new Character[0])); }
    //the relative paths to saved character files
    private ArrayList<String> characterPaths;
    /**
     * Returns the paths to the serialized character files.
     * @return The paths to the serialized character files.
     */
    public String[] getCharacterPaths(){ return(this.characterPaths.toArray(new String[0])); }
    /** 
     * Sets the Characters in this Area. 
     * @param characterPaths The relative paths to the serialized character files.
     * @param formatter The formatter to use to deserialize the characters.
     */
    public void setCharacters(String[] characterPaths,Formatter formatter){
        int length=characterPaths.length;
        this.characters=new ArrayList<Character>(length);
        this.characterPaths=new ArrayList<String>(length);
        for(int index=0;index<length;index++){
            try{
                String absoluteCharacterPath=PathResolver.getAbsolutePath(this.absoluteDir,characterPaths[index]);
                this.characters.add(CharacterFactory.load(absoluteCharacterPath,formatter));
                this.characterPaths.add(characterPaths[index]);
            } catch(UnsupportedCharacterException ucx){
                ucx.printStackTrace();
            }
        }
    }
    /**
     * Adds a Character to this Area.
     * @param characterPath The relative path to the serialized character files.
     * @param formatter The formatter to use to deserialize the characters.
     */
    public void addCharacter(String characterPath,Formatter formatter){ 
        try{
            String absoluteCharacterPath=PathResolver.getAbsolutePath(this.absoluteDir,characterPath);
            this.characters.add(CharacterFactory.load(absoluteCharacterPath,formatter));
            this.characterPaths.add(characterPath);
        } catch(UnsupportedCharacterException ucx){
            ucx.printStackTrace();   
        }
    }    
    //absolute path to the directory where characters are saved
    protected 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;
        }
        //set the absoluteDir for all layers
        Layer[] allLayers=this.getLayers();
        int length=allLayers.length;
        for(int index=0;index<length;index++){
            allLayers[index].setAbsoluteDir(absoluteDir);
        }
    }
/* end public properties */

/* begin constructors */
    /**
     * Creates a new instance of Area.
     */
    public Area(){
        this.layers=new ArrayList<Layer>();
        this.characters=new ArrayList<Character>();
        this.characterPaths=new ArrayList<String>();
    }
    /**      
     * Creates a new instance of Area.
     * @param layers The Layers for this Area.
     * @param characterPaths The relative paths to the serialized character files.
     * @param formatter The formatter to use to deserialize the characters.
     */
    public Area(Layer[] layers,String[] characterPaths,Formatter formatter){
        this.layers=new ArrayList<Layer>();
        this.characters=new ArrayList<Character>();
        this.characterPaths=new ArrayList<String>();
        this.setLayers(layers);
        this.setCharacters(characterPaths,formatter);
    }
/* end public properties */

/* begin public methods */
    /**
     * Get the character at the specified index.
     * @param index The index of the Character to get.
     * @return The character at the specified index.
     */
    public Character getCharacter(int index){
        if((index<0)||(index>=this.characters.size())){
            return(null);
        } 
        return(this.characters.get(index));
    }
    //get the layer at the specified index
    public Layer getLayer(int index){
        if((index<0)||(index>=this.layers.size())){
            return(null);
        } 
        return(this.layers.get(index));
    }
    /** 
     * 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);
        String[] characterPaths=this.getCharacterPaths();
        int length=characterPaths.length;
        this.characters=new ArrayList<Character>(length);
        this.characterPaths=new ArrayList<String>(length);
        for(int index=0;index<length;index++){
            try{
                String absoluteCharacterPath=PathResolver.getAbsolutePath(this.absoluteDir,characterPaths[index]);
                Character character=CharacterFactory.load(absoluteCharacterPath,formatter);
                this.characters.add(character);
                this.characterPaths.add(characterPaths[index]);
            } catch(UnsupportedCharacterException ucx){
                ucx.printStackTrace();
            }
        }
    }
/* end public methods */
}