package org.ntlab.radishforandroidstudio.cactusClient.models;


import java.util.HashMap;

import org.ntlab.radishforandroidstudio.framework.model3D.Position3D;
import org.ntlab.radishforandroidstudio.framework.model3D.Quaternion3D;



import net.arnx.jsonic.JSONHint;

public class Character extends Entity {
    private String accountURI;
    private String areaURI;
    private String name;
    private Position3D position;
    private Quaternion3D angle;
    private int modelID;

    private HashMap<String, Item> itemMap = new HashMap<>();
    @JSONHint(ignore = true)
    public static final int UNIQUE_ID_LENGTH = 12;

    private Character() {
        // JSONDecode時の呼び出し用
    }

    public Character(String instanceId, String accountURI, String name, Position3D position, Quaternion3D angle,
                     int modelID) {
        setAccountURI(accountURI);
        setName(name);
        setPosition(position);
        setQuaternion3D(angle);
        setModelID(modelID);
        initAreaURI(instanceId);
    }

    public String getAccountURI() {
        return accountURI;
    }

    public String getName() {
        return name;
    }

    public Position3D getPosition() {
        return position;
    }

    public Quaternion3D getQuaternion3D() {
        return angle;
    }

    public int getModelID() {
        return modelID;
    }

    public String getAreaURI() {
        return areaURI;
    }

    @JSONHint(ignore = true)
    public Item getItem(String itemId) {
        return itemMap.get(itemId);
    }

    @JSONHint(ignore = true)
    public HashMap<String, Item> getItems() {
        return itemMap;
    }

    public void setAccountURI(String accountURI) {
        this.accountURI = accountURI;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPosition(Position3D position) {
        this.position = position;
    }

    public void setQuaternion3D(Quaternion3D angle) {
        this.angle = angle;
    }

    public void setModelID(int modelID) {
        this.modelID = modelID;
    }

    public void setAreaURI(String areaURI) {
        this.areaURI = areaURI;
    }

    public HashMap<String, Item> createItem(String name, int amount) {
        Item item = new Item(name, amount);
        if (!hasItem(item)) {
            String id = RandomStringGenerator.generateUniqueString(Item.UNIQUE_ID_LENGTH,
                    RandomStringGenerator.ALPHA_NUMERIC, itemMap.keySet());
            itemMap.put(id, item);
            HashMap<String, Item> returnedMap = new HashMap<>();
            returnedMap.put(id, item);
            return returnedMap;
        }
        return null;
    }

    public boolean hasItem(Item item) {
        for (Item value : itemMap.values()) {
            if (value.equals(item)) {
                return true;
            }
        }
        return false;
    }

    public Item changeAmountOfItem(String itemId, int amountOfChange) {
        Item item = itemMap.get(itemId).changeAmount(amountOfChange);
        if (item.isEmpty()) {
            destroyItem(itemId);
        }
        return item;
    }

    private void initAreaURI(String instanceId) {
        Instance instance = Instances.getInstance().getInstance(instanceId);
        setAreaURI(findAreaURI(instance));
    }

    private String findAreaURI(Instance instance) {
        // キャラクターのポジションを用いてどのエリア内にいるかを判定して当該エリアのURIに更新する
        for (String areaId : instance.getAreas().keySet()) {
            Area area = instance.getArea(areaId);
            if (area.isSurroundingPosition(position)) {
                int subStringEndIndex = areaURI.length() - Area.UNIQUE_ID_LENGTH;
                StringBuilder newAreaURI = new StringBuilder();
                return newAreaURI.append(areaURI.substring(0, subStringEndIndex)).append(areaId).toString();
            }
        }
        return "";
    }

    public void update(Position3D position, Quaternion3D angle, String modelID, String areaURI) {
        setPosition(position);
        setQuaternion3D(angle);
        if (modelID != null) {
            setModelID(Integer.parseInt(modelID));
        }
        if (areaURI != null) {
            setAreaURI(areaURI);
        } else {
            updateAreaURI();
        }
    }

    private void updateAreaURI() {
        String[] areaURISplit = areaURI.split("/"); // ……/instances/{instanceId}/areas/{areaId}
        int splitSize = areaURISplit.length;
        String instanceId = areaURISplit[splitSize - 3];
        String previousAreaId = areaURISplit[splitSize - 1];
        Instance instance = Instances.getInstance().getInstance(instanceId);
        Area previousArea = instance.getArea(previousAreaId);
        if (!previousArea.isSurroundingPosition(position)) {
            // キャラクターのポジションを用いてどのエリア内にいるかを判定して当該エリアのURIに更新する
            setAreaURI(findAreaURI(instance));
        }
    }

    public Item destroyItem(String itemId) {
        return itemMap.remove(itemId);
    }
}