"""Player module, will use a strategy"""

import hand
import strategy

STAY = 0
HIT = 1
DOUBLE = 2
SPLIT = 3
# Default betting max and mins 
MINIMUM = 5
MAXIMUM = 300

def maximum(max_bet):
    """updates max bet"""
    global MAXIMUM
    MAXIMUM = max_bet

def minimum(min_bet):
    """updates min bet"""
    global MINIMUM
    MINIMUM = min_bet


class Player:
    """Player class takes a strategy and starting cash
    strategy: BASIC, PMC, RPC, and there will be RANDOM
    bet_strategy: RANDOM, PMC, RPC, and CONSTANT"""

    def __init__(self, strategy_name, bet_strategy, units, number_of_hands, cash):
        """initializes player"""
        self.cash = cash
        self.current_bet = 0
        self.strategy = strategy_name.upper()
        self.bet_strategy = bet_strategy.upper()
        self.units = units
        self.hand_count = number_of_hands
        self.hands = []
        self.current_hand = 0
        self.dealers_card = -1
        for i in xrange(number_of_hands):
            self.hands.append(hand.Hand())
        self.cash_history = [cash]
        self.move_history = []
        self.history = []

    def alive(self):
        """returns true if player has enough cash to play"""
        return MINIMUM < self.cash

    def deal(self, card, counts):
        """returns true if card was used false if not"""
        hand = self.hands[self.current_hand]
        while len(self.hands) > self.current_hand:
            if not hand.get_stand() and not hand.busted() and not hand.blackjack():
                move = strategy.move(hand.get_value(), self.dealers_card, hand.is_hard(),
                                        hand.can_split(), self.strategy, counts)
                if move >= 2 and self.cash < self.current_bet: # do not over bet cash
                    if move == DOUBLE:
                        hand.deal(card)
                        self.move_history.append(HIT)
                        return True 
                    elif move == SPLIT:
                        if hand.get_hand()[0] == 0: # strategy doesn't work nicely when we can't split aces
                            return HIT
                        move1 = strategy.move(hand.get_value(), self.dealers_card, hand.is_hard(),
                                        False, self.strategy, counts)
                        if move1 >= 1:
                            hand.deal(card)
                            self.move_history.append(HIT)
                            return True
                        else: # must be stand
                            self.move_history.append(STAY)
                            hand.stand()
                else: # have enough cash for any type of move
                    if move == STAY:
                        self.move_history.append(STAY)
                        hand.stand()
                    elif move == HIT:
                        self.move_history.append(HIT)
                        hand.deal(card)
                        return True
                    elif move == DOUBLE:
                        if hand.get_splitted_aces(): # (can't double on splitted aces)
                            hand.deal(card)
                        else:
                            self.move_history.append(DOUBLE)
                            self.cash -= self.current_bet
                            hand.doubledown(card)
                        return True
                    elif move == SPLIT:
                        self.move_history.append(SPLIT)
                        self.cash -= self.current_bet
                        self.hands.append(hand.split())
                        hand.deal(card)
                        return True
            self.current_hand += 1
        return False

    def initial_deal(self, dealers_card, cards):
        """deal the hands*2 initial cards"""
        self.dealers_card = dealers_card
        cur = 0
        for i in xrange(0, len(self.hands) * 2, 2):
            self.hands[cur].initial_deal((cards[i], cards[i+1]))
            cur += 1

    def bet(self, counts):
        """calculates the bet given count object"""
        if self.cash < MINIMUM:
            raise ValueError("out of cash: cannot bet")
        self.current_bet = strategy.bet(self.units, MINIMUM, MAXIMUM, self.cash, self.bet_strategy, counts)
        self.cash -= self.current_bet 
        for hand in self.hands:
            hand.set_bet(self.current_bet)

    def get_cash(self):
        """returns current cash"""
        return self.cash

    def get_high(self):
        """returns current high cash value"""
        return max(self.cash_history)

    def get_hand_count(self):
        """returns orginal number of playing hands."""
        return self.hand_count

    def get_current_hand_count(self):
        """returns current number of hands. this changes when hands are split"""
        return len(self.hands)

    def get_strategy(self):
        """returns strategy"""
        return self.strategy

    def get_units(self):
        """returns betting units"""
        return self.units

    def get_bet_strategy(self):
        """returns bet strategy"""

    def completed_hand(self, dealers_total, dealer_blackjack):
        """processes completed hand"""
        for hand in self.hands:
            status = hand.winning(dealers_total, dealer_blackjack)
            self.history.append(status[0]) # 0=lose, 1=push, 2=win, 3=blackjack
            self.cash += status[1]
        self.cash_history.append(self.cash)
        self.__reset_hand()

    def __reset_hand(self):
        """resets the hand after it completes"""
        for i in xrange(len(self.hands)):
            tmp = self.hands.pop()
            if not tmp.is_split():
                tmp.reset()
                self.hands.insert(0, tmp)
        self.current_hand = 0
        self.current_bet = 0
