package electrosphere.server.content.serialization;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.attach.AttachUtils;
import electrosphere.entity.types.EntityTypes;
import electrosphere.entity.types.EntityTypes.EntityType;
import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.foliage.FoliageUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerDataCell;
import electrosphere.util.Utilities;

/**
 * Contains all content for a given cell
 */
public class ContentSerialization {


    //The entities, serialized
    List<EntitySerialization> serializedEntities = new LinkedList<EntitySerialization>();

    /**
     * Constructs a content serialization of a given list of entities
     * @param entities The entities
     * @return The content serialization
     */
    public static ContentSerialization constructContentSerialization(Collection<Entity> entities){
        ContentSerialization rVal = new ContentSerialization();
        for(Entity entity : entities){
            if(!CreatureUtils.hasControllerPlayerId(entity)){
                EntityType type = CommonEntityUtils.getEntityType(entity);
                if(type != null){
                    switch(type){
                        case CREATURE: {
                            EntitySerialization serializedEntity = new EntitySerialization();
                            serializedEntity.setPosition(EntityUtils.getPosition(entity));
                            serializedEntity.setRotation(EntityUtils.getRotation(entity));
                            serializedEntity.setType(EntityType.CREATURE.getValue());
                            serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
                            if(CreatureUtils.getCreatureTemplate(entity) != null){
                                serializedEntity.setTemplate(Utilities.stringify(CreatureUtils.getCreatureTemplate(entity)));
                            }
                            rVal.serializedEntities.add(serializedEntity);
                        } break;
                        case ITEM: {
                            if(!AttachUtils.isAttached(entity)){
                                EntitySerialization serializedEntity = new EntitySerialization();
                                serializedEntity.setPosition(EntityUtils.getPosition(entity));
                                serializedEntity.setRotation(EntityUtils.getRotation(entity));
                                serializedEntity.setType(EntityType.ITEM.getValue());
                                serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
                                rVal.serializedEntities.add(serializedEntity);
                            }
                        } break;
                        case FOLIAGE: {
                            EntitySerialization serializedEntity = new EntitySerialization();
                            serializedEntity.setPosition(EntityUtils.getPosition(entity));
                            serializedEntity.setRotation(EntityUtils.getRotation(entity));
                            serializedEntity.setType(EntityType.FOLIAGE.getValue());
                            serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
                            serializedEntity.setTemplate(FoliageUtils.getFoliageSeed(entity) + "");
                            rVal.serializedEntities.add(serializedEntity);
                        } break;
                        case COMMON: {
                            EntitySerialization serializedEntity = new EntitySerialization();
                            serializedEntity.setPosition(EntityUtils.getPosition(entity));
                            serializedEntity.setRotation(EntityUtils.getRotation(entity));
                            serializedEntity.setType(EntityType.COMMON.getValue());
                            serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
                            rVal.serializedEntities.add(serializedEntity);
                        } break;
                    }
                }
            }
        }
        return rVal;
    }

    /**
     * Actually creates the entities from a content serialization
     * @param contentRaw The content serialization
     */
    public void hydrateRawContent(Realm realm, ServerDataCell serverDataCell){
        List<EntitySerialization> serializedEntities = this.getSerializedEntities();
        for(EntitySerialization serializedEntity : serializedEntities){
            switch(EntityTypes.fromInt(serializedEntity.getType())){
                case CREATURE: {
                    CreatureTemplate template = null;
                    if(serializedEntity.getTemplate() != null){
                        template = Utilities.deserialize(serializedEntity.getTemplate(), CreatureTemplate.class);
                    }

                    //
                    //Spawn the creature itself
                    Entity creature = CreatureUtils.serverSpawnBasicCreature(realm, serializedEntity.getPosition(), serializedEntity.getSubtype(), template);
                    CreatureUtils.serverApplyTemplate(realm, creature, template);
                    EntityUtils.getRotation(creature).set(serializedEntity.getRotation());
                } break;
                case ITEM: {
                    Entity item = ItemUtils.serverSpawnBasicItem(realm, serializedEntity.getPosition(), serializedEntity.getSubtype());
                    EntityUtils.getRotation(item).set(serializedEntity.getRotation());
                } break;
                case COMMON: {
                    Entity object = CommonEntityUtils.serverSpawnBasicObject(realm, serializedEntity.getPosition(), serializedEntity.getSubtype());
                    EntityUtils.getRotation(object).set(serializedEntity.getRotation());
                } break;
                case FOLIAGE: {
                    long seed = Long.parseLong(serializedEntity.getTemplate());
                    Entity foliage = FoliageUtils.serverSpawnTreeFoliage(realm, serializedEntity.getPosition(), serializedEntity.getSubtype(), seed);
                    EntityUtils.getRotation(foliage).set(serializedEntity.getRotation());
                } break;
            }
        }
    }

    /**
     * Gets all serialized entities
     * @return the list of serialized entities
     */
    public List<EntitySerialization> getSerializedEntities(){
        return serializedEntities;
    }
    
}
