package player.tasks;

import logging.Logger;
import scg.Util;
import scg.gen.AcceptTrans;
import scg.gen.OfferedChallenge;
import scg.gen.PlayerContext;
import scg.gen.Config;
import edu.neu.ccs.demeterf.lib.List;

/** Accept Challenges we want to solve... choose wisely :) */
public class AcceptTask {

    protected final Logger log;

    /** Create a AcceptTask with the given Logger */
    public AcceptTask(Logger l){ log = l; }

    /** Do the actual acceptances */
    public List<AcceptTrans> accept(final PlayerContext context){
        log.notify("With Account: $" + context.getBalance());
        List<OfferedChallenge> chs = context.getTheirOffered();
        return chs.fold(new List.Fold<OfferedChallenge, Accepts>() {

            public Accepts fold(OfferedChallenge off, Accepts acc){
                if (!acc.shouldAccept(off, context.getConfig())) {
                    //log.notify("Not Accepting : #" + off.getKey());
                    return acc;
                }
                log.notify(":) Accepting : #" + off.getKey());
                return acc.doAccept(off);
            }
        }, new Accepts(context.getBalance())).getTransactions();
    }

    /** Will we be able to make a proffit? */
    protected boolean profitable(OfferedChallenge off, Config config){
        return Util.coinFlip();
    }    
    
    /** Keeps track of our account balance and what we've accepted so far.
     * Obviously more complicated schemes are possible (and suggested) */
    private class Accepts {
        double account;
        List<AcceptTrans> toget;

        /** Full Constructor */
        Accepts(double a, List<AcceptTrans> get) { account = a; toget = get; }

        /** Starts with the empty list of Accept Transactions */
        Accepts(double a){ this(a, List.<AcceptTrans> create()); }

        /** Should this OfferedChallenge be accepted? Change this to implement
         * your Challenge selection choices. */
        boolean shouldAccept(OfferedChallenge off, Config config){
            return off.getPrice() < account && profitable(off,config);
        }
        /** Do the 'accepting' of the Challenge */
        Accepts doAccept(OfferedChallenge off)
        { return new Accepts(account - off.getPrice(), toget.push(new AcceptTrans(off.getKey()))); }

        /** Return the accumulated Accept Transactions */
        public List<AcceptTrans> getTransactions(){ return toget; }
    }
}

