/* **********************************
 *   StoreUpdater.java
 *     StoreUpdater
 * **********************************/
package admin.utils;

import utils.comparator.SameDerivative;
import edu.neu.ccs.demeterf.*;
import edu.neu.ccs.demeterf.demfgen.lib.List;
import gen.*;
import utils.*;

/** Class for updating the store after each player transaction */
public class StoreUpdater extends ListTUCombiner<Pair<PlayerID, PlayerStore>>{    
    private PlayerID pID;
    Pair<PlayerID, PlayerStore> playerStore;
    private Store store;

    public StoreUpdater(PlayerID playerID, Store st){
        store = st;
        pID = playerID;
    }
    
    static List<Derivative> empty = List.create();
    Pair<PlayerID, PlayerStore> getPlayerStore(){
        // Lookup the player's stuff...
        if(!store.contains(pID))
            store = store.add(new Pair<PlayerID, PlayerStore>(pID, new PlayerStore(empty,empty)));
        return store.getStorePair(pID);
    }
    
    public static Store updateStore(Store store, PlayerTransaction pTrans){
        StoreUpdater update = new StoreUpdater(pTrans.player.id, store);
        TUCombiner.traverse(pTrans, update,
                Control.builtins(Derivative.class,TransactionType.class));
        return update.store;
    }
    TransactionType combine(TransactionType t){ return t; }

    @SuppressWarnings("unchecked")
	List<Pair<PlayerID, PlayerStore>> combine(Transaction trans, Buy b){
        //include the bought der in the bought store of the player
        Pair<PlayerID, PlayerStore> pStore = getPlayerStore();
        pStore.b.bought = pStore.b.bought.push(trans.deriv.buy(pID));
        
        //remove the bought der from the forSale store of the seller
        Pair<PlayerID, PlayerStore> pStore2 = store.getStorePair(trans.deriv.seller);
        pStore2.b.forSale = pStore2.b.forSale.remove(new SameDerivative(trans.deriv));
        
        //make changes to the store
        store = store.replace(pStore);
        store = store.replace(pStore2);
        return List.create(pStore, pStore2);
    }
    
    @SuppressWarnings("unchecked")
	List<Pair<PlayerID, PlayerStore>> combine(Transaction trans, Finish b){
        // remove the derivative from the boughtStore of the player
        Pair<PlayerID, PlayerStore> pStore = getPlayerStore();
        
        pStore.b.bought = pStore.b.bought.remove(new SameDerivative(trans.deriv));
        store = store.replace(pStore);
        return List.<Pair<PlayerID, PlayerStore>>create(pStore);        
    }
    
    @SuppressWarnings("unchecked")
	List<Pair<PlayerID, PlayerStore>> combine(Transaction trans, Create b){
        // include the derivative in the forSale store of the player
        Pair<PlayerID, PlayerStore> pStore = getPlayerStore();
        
        pStore.b.forSale = pStore.b.forSale.push(trans.deriv);
        store = store.replace(pStore);
        return List.<Pair<PlayerID, PlayerStore>>create(pStore);
    }
    
    @SuppressWarnings("unchecked")
	List<Pair<PlayerID, PlayerStore>> combine(Transaction trans, Deliver b){
        //update the derivative in the boughtStore of the buyer
        Pair<PlayerID, PlayerStore> pStore = store.getStorePair(trans.deriv.optbuyer.inner());
        pStore.b.bought = pStore.b.bought.replace(new SameDerivative(trans.deriv), trans.deriv);
        store = store.replace(pStore);
        return List.<Pair<PlayerID, PlayerStore>>create(pStore);
    }
    
    @SuppressWarnings("unchecked")
	List<Pair<PlayerID, PlayerStore>> combine(Transaction trans, Reoffer b){
        Pair<PlayerID, PlayerStore> pStore = getPlayerStore();
        
        pStore.b.forSale = pStore.b.forSale.push(trans.deriv);
        store = store.replace(pStore);
        return List.<Pair<PlayerID, PlayerStore>>create(pStore);
    }
}