/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

/**
 *
 * @author eccastro
 */
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import com.jme.renderer.ColorRGBA;
import com.jme.util.export.InputCapsule;
import com.jme.util.export.OutputCapsule;
import com.jme.util.export.Savable;
import java.util.Observable;
import util.Constants;

public class Knapsack extends Observable implements Savable {

    //Crystals:
    public List<Jewel> jewelPool; //not in use
    public HashMap<String, Food> foodMap;
    public HashMap<String, IntegerSavable> numberOfJewels;
    public HashMap<String, IntegerSavable> numberOfFood;

    public int score;
    IntegerSavable g;
    IntegerSavable r;
    IntegerSavable bl;
    IntegerSavable y;
    IntegerSavable p;
    IntegerSavable m;
    IntegerSavable br;
    IntegerSavable lg;
    IntegerSavable dg;
    IntegerSavable or;
    IntegerSavable pFood;
    IntegerSavable npFood;

    public Knapsack() {

        numberOfJewels = new HashMap();
        foodMap = new HashMap();
        numberOfFood = new HashMap();
        //initKnapsack();
        init();
        score = 0; 
    }

    public int getScore() {
        return score;
    }

    public void incScore(int pts) {
        score = score + pts;
    }

    public void decScore(int pts) {
        score = score - pts;
    }

    public void resetScore() {
        score = 0;
    }
//    public void putInKnapsack(String color) {
//
//        incKnapsack(color);
//    }
//

    public void removeJewelFromKnapsack(String color) {

        decJewelInKnapsack(color);
    }

    /**
     * Currently not in use.
     * @param o
     */
    public void putInKnapsack(Jewel o) {
        jewelPool.add(o);
        incKnapsack(o);
    }

    /**
     * Currently not in use.
     * @param o
     */
    public void removeJewelFromKnapsack(Jewel o) {
        jewelPool.remove(o);
        decKnapsack(o);
    }

    public void init() {
        int g_ = 0;
        int r_ = 0;
        int br_ = 0;
        int y_ = 0;
        int p_ = 0;
        int m_ = 0;
        int bl_ = 0;
        int lg_ = 0;
        int dg_ = 0;
        int or_ = 0;

        int pFood_ = 0;
        int npFood_ = 0;

        this.g = new IntegerSavable(g_);
        this.r = new IntegerSavable(r_);
        this.bl = new IntegerSavable(bl_);
        this.y = new IntegerSavable(y_);
        this.p = new IntegerSavable(p_);
        this.m = new IntegerSavable(m_);
        this.br = new IntegerSavable(br_);
        this.lg = new IntegerSavable(lg_);
        this.dg = new IntegerSavable(dg_);
        this.or = new IntegerSavable(or_);

        this.pFood = new IntegerSavable(pFood_);
        this.npFood = new IntegerSavable(npFood_);

        numberOfJewels.put(Constants.colorGREEN, this.g);
        numberOfJewels.put(Constants.colorRED, this.r);
        numberOfJewels.put(Constants.colorBLUE, this.bl);
        numberOfJewels.put(Constants.colorYELLOW, this.y);
        //numberOfObstacles.put("Pink", this.p);
        numberOfJewels.put(Constants.colorMAGENTA, this.m);
        //numberOfObstacles.put("Brown", this.br);
        numberOfJewels.put(Constants.colorWHITE, this.lg);
        numberOfJewels.put(Constants.colorDARKGRAY, this.dg);
        numberOfJewels.put(Constants.colorORANGE, this.or);

        numberOfFood.put(Constants.PFOOD, this.pFood);
        numberOfFood.put(Constants.NPFOOD, this.npFood);
    }

    public void incJewelInKnapsack(String color) {

        //System.out.println("======= Color is " + color);
        numberOfJewels.put(color, new IntegerSavable(numberOfJewels.get(color).intValue() + 1));
        notifyMyObservers();
    }

    public void decJewelInKnapsack(String color) {
        if (numberOfJewels.get(color).intValue() > 0) {
            numberOfJewels.put(color, new IntegerSavable(numberOfJewels.get(color).intValue() - 1));
            //System.out.println("======= Color " + color + " delivered.");
            notifyMyObservers();
        }
    }

    public void incPerishableFoodInKnapsack() {
        numberOfFood.put(Constants.PFOOD, new IntegerSavable(numberOfFood.get(Constants.PFOOD).intValue() + 1));
        notifyMyObservers();
    }

    public void incPerishableFoodInKnapsack(Food food) {

        //System.out.println("======= Put PFood: " + food.getMyName() + " in knapsack.");
        foodMap.put(food.getMyName(), food);
        numberOfFood.put(Constants.PFOOD, new IntegerSavable(numberOfFood.get(Constants.PFOOD).intValue() + 1));
        notifyMyObservers();

    }

    public void decPerishableFoodInKnapsack() {
        numberOfFood.put(Constants.PFOOD, new IntegerSavable(numberOfFood.get(Constants.PFOOD).intValue() - 1));
        notifyMyObservers();

    }

    /**
     *
     * @param name Name of the food to be removed.
     */
    public void decPerishableFoodInKnapsack(String name) {

        //System.out.println("======= Remove PFood: " + name + " from knapsack.");
        foodMap.remove(name);
        numberOfFood.put(Constants.PFOOD, new IntegerSavable(numberOfFood.get(Constants.PFOOD).intValue() - 1));
        notifyMyObservers();

    }

    public void incNonPerishableFoodInKnapsack(Food food) {
        //System.out.println("======= Put NPFood: " + food.getMyName() + " in knapsack.");
        foodMap.put(food.getMyName(), food);
        numberOfFood.put(Constants.NPFOOD, new IntegerSavable(numberOfFood.get(Constants.NPFOOD).intValue() + 1));
        notifyMyObservers();

    }


    public void incNonPerishableFoodInKnapsack() {
        numberOfFood.put(Constants.NPFOOD, new IntegerSavable(numberOfFood.get(Constants.NPFOOD).intValue() + 1));
        notifyMyObservers();

    }

    public void decNonPerishableFoodInKnapsack() {
        numberOfFood.put(Constants.NPFOOD, new IntegerSavable(numberOfFood.get(Constants.NPFOOD).intValue() - 1));
        notifyMyObservers();

    }

    public void decNonPerishableFoodInKnapsack(String name) {
        //System.out.println("======= Remove NPFood: " + name + " from knapsack.");
        foodMap.remove(name);
        numberOfFood.put(Constants.NPFOOD, new IntegerSavable(numberOfFood.get(Constants.NPFOOD).intValue() - 1));
        notifyMyObservers();

    }

    private void incKnapsack(Jewel o) {

        if (o.getMaterial().getColor() == ColorRGBA.green) {
            numberOfJewels.put(Constants.colorGREEN, new IntegerSavable(numberOfJewels.get(Constants.colorGREEN).intValue() + 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.red) {
            numberOfJewels.put(Constants.colorRED, new IntegerSavable(numberOfJewels.get(Constants.colorRED).intValue() + 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.blue) {
            numberOfJewels.put(Constants.colorBLUE, new IntegerSavable(numberOfJewels.get(Constants.colorBLUE).intValue() + 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.yellow) {
            numberOfJewels.put(Constants.colorYELLOW, new IntegerSavable(numberOfJewels.get(Constants.colorYELLOW).intValue() + 1));
        } //            else if (o.getMaterial().getColor() == ColorRGBA.pink)
        //                numberOfObstacles.put("Pink", new Integer(numberOfObstacles.get("Pink").intValue() +1));
        else if (o.getMaterial().getColor() == ColorRGBA.magenta) {
            numberOfJewels.put(Constants.colorMAGENTA, new IntegerSavable(numberOfJewels.get(Constants.colorMAGENTA).intValue() + 1));
        } //            else if (o.getMaterial().getColor() == ColorRGBA.brown)
        //                numberOfObstacles.put("Brown", new Integer(numberOfObstacles.get("Brown").intValue() +1));
        else if (o.getMaterial().getColor() == ColorRGBA.white) {
            numberOfJewels.put(Constants.colorWHITE, new IntegerSavable(numberOfJewels.get(Constants.colorWHITE).intValue() + 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.darkGray) {
            numberOfJewels.put(Constants.colorDARKGRAY, new IntegerSavable(numberOfJewels.get(Constants.colorDARKGRAY).intValue() + 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.orange) {
            numberOfJewels.put(Constants.colorORANGE, new IntegerSavable(numberOfJewels.get(Constants.colorORANGE).intValue() + 1));
        }

        notifyMyObservers();
    }

    private void decKnapsack(Jewel o) {

        if (o.getMaterial().getColor() == ColorRGBA.green) {
            numberOfJewels.put(Constants.colorGREEN, new IntegerSavable(numberOfJewels.get(Constants.colorGREEN).intValue() - 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.red) {
            numberOfJewels.put(Constants.colorRED, new IntegerSavable(numberOfJewels.get(Constants.colorRED).intValue() - 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.blue) {
            numberOfJewels.put(Constants.colorBLUE, new IntegerSavable(numberOfJewels.get(Constants.colorBLUE).intValue() - 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.yellow) {
            numberOfJewels.put(Constants.colorYELLOW, new IntegerSavable(numberOfJewels.get(Constants.colorYELLOW).intValue() - 1));
        } //            else if (o.getMaterial().getColor() == ColorRGBA.pink)
        //                numberOfObstacles.put("Pink", new Integer(numberOfObstacles.get("Pink").intValue() -1));
        else if (o.getMaterial().getColor() == ColorRGBA.magenta) {
            numberOfJewels.put(Constants.colorMAGENTA, new IntegerSavable(numberOfJewels.get(Constants.colorMAGENTA).intValue() - 1));
        } //            else if (o.getMaterial().getColor() == ColorRGBA.brown)
        //                numberOfObstacles.put("Brown", new Integer(numberOfObstacles.get("Brown").intValue() -1));
        else if (o.getMaterial().getColor() == ColorRGBA.white) {
            numberOfJewels.put(Constants.colorWHITE, new IntegerSavable(numberOfJewels.get(Constants.colorWHITE).intValue() - 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.darkGray) {
            numberOfJewels.put(Constants.colorDARKGRAY, new IntegerSavable(numberOfJewels.get(Constants.colorDARKGRAY).intValue() - 1));
        } else if (o.getMaterial().getColor() == ColorRGBA.orange) {
            numberOfJewels.put(Constants.colorORANGE, new IntegerSavable(numberOfJewels.get(Constants.colorORANGE).intValue() - 1));
        }

        notifyMyObservers();
    }

    public Integer getNumberOfJewels(String color) {

        return numberOfJewels.get(color).value;
    }

    public Integer getNumberOfFood(String name) {

        return numberOfFood.get(name).value;
    }

    public void notifyMyObservers() {
        setChanged();
        notifyObservers(new Long(0));
    }

    public void write(JMEExporter jmee) throws IOException {
        OutputCapsule capsule = jmee.getCapsule(this);
        capsule.writeSavableArrayList((ArrayList) jewelPool, "jewelPool", null);
        capsule.writeStringSavableMap(foodMap, "foodMap", null);
        capsule.writeStringSavableMap(numberOfJewels, "numberOfJewels", null);
        capsule.writeStringSavableMap(numberOfFood, "numberOfFood", null);
        capsule.write(score, "score", 0);
        capsule.write(g, "g", null);
        capsule.write(r, "r", null);
        capsule.write(bl, "bl", null);
        capsule.write(y, "y", null);
        capsule.write(p, "p", null);
        capsule.write(m, "m", null);
        capsule.write(br, "br", null);
        capsule.write(lg, "lg", null);
        capsule.write(dg, "dg", null);
        capsule.write(or, "or", null);
        capsule.write(pFood, "pFood", null);
        capsule.write(npFood, "npFood", null);

    }

    public void read(JMEImporter jmei) throws IOException {
        InputCapsule ic = jmei.getCapsule(this);
        jewelPool = ic.readSavableArrayList("jewelPool", null);
        foodMap = (HashMap<String, Food>) ic.readStringSavableMap("foodMap", null);
        numberOfJewels = (HashMap<String, IntegerSavable>) ic.readStringSavableMap("numberOfJewels", null);
        numberOfFood = (HashMap<String, IntegerSavable>) ic.readStringSavableMap("numberOfFood", null);

        score = ic.readInt("score", 0);
        g = (IntegerSavable) ic.readSavable("g", null);
        r = (IntegerSavable) ic.readSavable("r", null);
        bl = (IntegerSavable) ic.readSavable("bl", null);
        y = (IntegerSavable) ic.readSavable("y", null);
        p = (IntegerSavable) ic.readSavable("p", null);
        m = (IntegerSavable) ic.readSavable("m", null);
        br = (IntegerSavable) ic.readSavable("br", null);
        lg = (IntegerSavable) ic.readSavable("lg", null);
        dg = (IntegerSavable) ic.readSavable("dg", null);
        or = (IntegerSavable) ic.readSavable("or", null);
        pFood = (IntegerSavable) ic.readSavable("pFood", null);
        npFood = (IntegerSavable) ic.readSavable("npFood", null);

    }

    public Class getClassTag() {
        return this.getClass();
    }

    public class IntegerSavable implements Savable {

        public Integer value = new Integer(0);

        public IntegerSavable(int value) {
            this.value = value;
        }

        public int intValue() {
            return value.intValue();
        }

        public void write(JMEExporter jmee) throws IOException {
            OutputCapsule capsule = jmee.getCapsule(this);
            capsule.write(value, "value", 0);

        }

        public void read(JMEImporter jmei) throws IOException {
            InputCapsule ic = jmei.getCapsule(this);
            value = ic.readInt("value", 0);
        }

        public Class getClassTag() {
            return this.getClass();
        }
    }
}
