/* **********************************
 *   Util.java
 *     Administrator Utility Methods
 * **********************************/
package admin;

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

/** Utility Class */
public class Util {
    /** Admin Print Method */
    static void _print(String s){ System.err.println(s); }
    
    /** Create a Pair for the Store/Accounts */
    public static Pair<PlayerID,Double> pair(PlayerID pid, Double d){ return new Pair<PlayerID,Double>(pid,d); }
    public static Pair<PlayerID,PlayerStore> spair(PlayerID pid, PlayerStore d){ return new Pair<PlayerID,PlayerStore>(pid,d); }
    
    /** Calculates the quality of all derivatives finished in pTrans */
    public static PlayerTransaction computeQualities(PlayerTransaction pTrans){
        return SetQualities.setQs(pTrans, Control.builtins(Derivative.class));
    }
    
    /** Truncate the Transaction RawMaterials */
    public static PlayerTransaction truncateRMs(PlayerTransaction pTrans, final int len){
        return new PlayerTransaction(pTrans.player,pTrans.transactions.map(new List.Map<Transaction, Transaction>(){
            public Transaction map(Transaction t){
                return new Transaction(t.ttype, t.deriv.truncateRM(len));
            }
        }));
    }
    /** Check/replace the correct information from the store */
    public static PlayerTransaction checkDerivatives(final PlayerTransaction pTrans, final Store store){
        final List<Derivative> ders = DerivativesFinder.findActiveDers(store.stores);
        return new PlayerTransaction(pTrans.player,pTrans.transactions.map(new List.Map<Transaction, Transaction>(){
            public Transaction map(Transaction t){
                if(t.ttype instanceof Create || !ders.contains(new Which(t.deriv)))return t;
                Derivative target = ders.find(new Which(t.deriv));
                if(t.ttype instanceof Buy){
                    // Nothing to do... just keep the old one
                }else if(t.ttype instanceof Reoffer){
                    target = t.deriv;
                }else if(t.ttype instanceof Deliver){
                    target = ders.find(new PreDeliver(t.deriv));
                    target = target.deliver(t.deriv.optraw.inner().instance);
                }else if(t.ttype instanceof Finish){
                    target = ders.find(new PreFinish(t.deriv));
                    target = target.finish(t.deriv.optfinished.inner());
                }
                return new Transaction(t.ttype, target);
            }
        }));
    }
    
    /** Class to determine whether two derivatives are same */
    static class Which extends Pred<Derivative>{
        Derivative forwrd;
        Which(Derivative f){ forwrd = f; }

        public boolean huh(Derivative d){
            return (d.name.equals(forwrd.name) &&
                    d.price.equals(forwrd.price) &&
                    d.seller.equals(forwrd.seller) &&
                    d.type.equals(forwrd.type));
        }    
    }
    static class PreDeliver extends Which{
        PreDeliver(Derivative f){ super(f); }
        public boolean huh(Derivative d){
            return super.huh(d) && d.optbuyer.isSome() && d.optbuyer.equals(forwrd.optbuyer) && 
                                   !d.optraw.isSome();
        }
    }
    static class PreFinish extends Which{
        PreFinish(Derivative f){ super(f); }
        public boolean huh(Derivative d){
            return super.huh(d) && d.optbuyer.isSome() && d.optbuyer.equals(forwrd.optbuyer) && 
                                   d.optraw.isSome() && !d.optfinished.isSome();    
        }
    }
}