package de.frajul.endlessroll.entities.tools;

import android.support.annotation.Nullable;
import android.support.annotation.StringRes;

import java.util.Arrays;
import java.util.List;

import de.frajul.endlessroll.R;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.entities.textures.TexturePack;
import de.frajul.endlessroll.sounds.SoundManager;

public enum ToolType {

    //Check newInstance when new Tool is added!
    RAMP(R.string.tool_name_ramp, R.string.tool_description_ramp, R.drawable.tools_ramp,
            R.drawable.tools_ramp_button, R.raw.ramp, 0, 1, 5,
            new ToolUpgrade(ToolUpgradeType.COOLDOWN, 3000, 1000)),
    SPRING(R.string.tool_name_spring, R.string.tool_description_spring, R.drawable.tools_spring,
            R.drawable.tools_spring_button, R.raw.ramp, 5, 2, 5,
            new ToolUpgrade(ToolUpgradeType.COOLDOWN, 4000, 2000)),
    BOMB(R.string.tool_name_bomb, R.string.tool_description_bomb, R.drawable.tools_bomb,
            R.drawable.tools_bomb_button, R.raw.ramp, 12, 4, 5,
            new ToolUpgrade(ToolUpgradeType.COOLDOWN, 6000, 4000),
            new ToolUpgrade(ToolUpgradeType.DURATION, 1200, 400),
            new ToolUpgrade(ToolUpgradeType.RANGE, 100, 200)),
    MAGNET(R.string.tool_name_magnet, R.string.tool_description_magnet, R.drawable.tools_magnet,
            R.drawable.tools_magnet_button, R.raw.ramp, 10, 4, 5,
            new ToolUpgrade(ToolUpgradeType.COOLDOWN, 6000, 4000),
            new ToolUpgrade(ToolUpgradeType.FORCE, 100, 500)),
    POWER_MUSHROOM(R.string.tool_name_power_mushroom, R.string.tool_description_power_mushroom,
            R.drawable.tools_power_mushroom, R.drawable.tools_power_mushroom_button, R.raw.ramp, 5,
            5, 7, new ToolUpgrade(ToolUpgradeType.COOLDOWN, 15000, 11000),
            new ToolUpgrade(ToolUpgradeType.DURATION, 5000, 10000)),
    STASIS(R.string.tool_name_stasis, R.string.tool_description_stasis, R.drawable.tools_stasis,
            R.drawable.tools_stasis_button, R.raw.ramp, 15, 6, 6,
            new ToolUpgrade(ToolUpgradeType.COOLDOWN, 8000, 5000),
            new ToolUpgrade(ToolUpgradeType.FORCE, 1, 2),
            new ToolUpgrade(ToolUpgradeType.SIZE, 100, 200));

    @StringRes
    private final int name;
    @StringRes
    private final int description;
    private final int toolTextureId;
    private final int buttonDrawable;
    private final int placingSoundId;
    private final int buyPrice;
    private final int upgradePrice;
    private final int maxUpgradeLevel;
    private final List<ToolUpgrade> upgrades;

    private Texture toolTexture = null;
    private int placingSound = -1;
    private boolean bought;
    private int currentUpgradeLevel = 1;

    ToolType(@StringRes int name, @StringRes int description, int toolTextureId, int buttonDrawable, int placingSoundId, int buyPrice, int upgradePrice, int maxUpgradeLevel, ToolUpgrade... upgrades) {
        this.name = name;
        this.description = description;
        this.toolTextureId = toolTextureId;
        this.buttonDrawable = buttonDrawable;
        this.placingSoundId = placingSoundId;
        this.buyPrice = buyPrice;
        this.upgradePrice = upgradePrice;
        this.maxUpgradeLevel = maxUpgradeLevel;
        this.upgrades = Arrays.asList(upgrades);
    }

    @Nullable
    public Tool newInstance(Vector position, ParticleSystem particleSystem) {
        Tool tool = null;
        switch (this) {
            case RAMP:
                tool = new Ramp(position);
                break;
            case SPRING:
                tool = new Spring(position);
                break;
            case MAGNET:
                tool = new Magnet(position, particleSystem);
                break;
            case BOMB:
                tool = new Bomb(position);
                break;
            case POWER_MUSHROOM:
                tool = new PowerMushroom(position);
                break;
            case STASIS:
                tool = new Stasis(position,particleSystem);
                break;
        }
        if (tool != null && tool.isPlacedByRightEdge())
            tool.move(new Vector(-tool.getWidth() / 2, 0));
        return tool;
    }

    public static void loadAllPlacingSounds(SoundManager soundManager) {
        for (ToolType type : values())
            type.loadPlacingSound(soundManager);
    }

    public static void loadAllToolTextures(TexturePack texturePack) {
        for (ToolType type : values())
            type.loadToolTexture(texturePack);
    }

    private void loadPlacingSound(SoundManager soundManager) {
        if (placingSoundId == -1)
            return;
        placingSound = soundManager.loadSound(placingSoundId);
    }

    private void loadToolTexture(TexturePack texturePack) {
        if (toolTextureId == -1)
            return;
        if (this != POWER_MUSHROOM)
            toolTexture = texturePack.loadAtlas(toolTextureId, 2, 2);
        else
            toolTexture = texturePack.loadTexture(toolTextureId);
    }

    public Texture getToolTexture() {
        return toolTexture;
    }

    public int getButtonDrawable() {
        return buttonDrawable;
    }

    public int getPlacingSound() {
        return placingSound;
    }

    @StringRes
    public int getName() {
        return name;
    }

    @StringRes
    public int getDescription() {
        return description;
    }

    public void setBought(boolean bought) {
        this.bought = bought;
    }

    public boolean isBought() {
        if (this == RAMP)
            bought = true;
        return bought;
    }

    public void upgrade() {
        currentUpgradeLevel++;
    }

    public void reset() {
        setBought(false);
        currentUpgradeLevel = 1;
    }

    public int getBuyPrice() {
        return buyPrice;
    }

    public int getUpgradePrice() {
        return upgradePrice + currentUpgradeLevel - 1;
    }

    public int getCurrentUpgradeLevel() {
        return currentUpgradeLevel;
    }

    public void setCurrentUpgradeLevel(int currentUpgradeLevel) {
        this.currentUpgradeLevel = currentUpgradeLevel;
    }

    public float getCurrentUpgradeValue(ToolUpgradeType type) {
        for (ToolUpgrade upgrade : upgrades)
            if (upgrade.getType().equals(type))
                return upgrade.getValueAtLevel(currentUpgradeLevel, maxUpgradeLevel);
        return -1;
    }

    public boolean isAtMaxUpgradeLevel() {
        return currentUpgradeLevel == maxUpgradeLevel;
    }

}