import random
import json
import math

from shutil import copyfile

from funcs import logThis, replaceMultiple
from . import money, blackjackDraw

# Shuffles the blackjack cards
def blackjackShuffle(decks):
    logThis("Shuffling the blackjack deck")

    with open("resources/games/deckofCards.txt","r") as f:
        deck = f.read()
    
    allDecks = deck.split("\n") * decks
    random.shuffle(allDecks)
    data = "\n".join(allDecks)

    with open("resources/games/blackjackCards.txt","w") as f:
        f.write(data)

    return

# Calculates the value of a blackjack hand
def calcHandValue(hand : list):
    logThis("Calculating hand value")
    values = [0]

    for card in hand:
        cardValue = card[0]
        cardValue = replaceMultiple(cardValue,["0","k","q","j"],"10")
        if cardValue == "a":
            length = len(values)
            for x in range(length):
                values.append(values[x] + 11)
                values[x] += 1
        else:
            for x in range(len(values)):
                values[x] += int(cardValue)
    
    values.sort()

    handValue = values[0]
    for value in values:
        if value <= 21:
            handValue = value

    logThis("Calculated "+str(hand)+" to be "+str(handValue))

    return handValue

# Draws a card from the deck
def drawCard():
    logThis("drawing a card")
    with open("resources/games/blackjackCards.txt","r") as f:
        cards = f.read().split("\n")
    
    drawnCard = cards.pop(0)
    data = "\n".join(cards)

    with open("resources/games/blackjackCards.txt","w") as f:
        f.write(data)

    return drawnCard

# Dealer draws a card and checks if they should draw another one
def dealerDraw(channel):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)
    
    done = False
    dealerHand = data["blackjack games"][channel]["dealer hand"]

    if calcHandValue(dealerHand) < 17:
        data["blackjack games"][channel]["dealer hand"].append(drawCard())
    else:
        done = True
    
    if calcHandValue(dealerHand) > 21:
        data["blackjack games"][channel]["dealer busted"] = True

    with open("resources/games/games.json", "w") as f:
        json.dump(data,f,indent=4)
    
    return done

# Goes to the next round and calculates some stuff
def blackjackContinue(channel):
    logThis("Continuing blackjack game")
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)

    done = False

    data["blackjack games"][channel]["round"] += 1

    with open("resources/games/games.json", "w") as f:
        json.dump(data,f,indent=4)
    
    allStanding = True
    preAllStanding = True
    message = "All players are standing. The dealer now shows his cards and draws."

    if data["blackjack games"][channel]["all standing"]:
        with open("resources/games/games.json", "w") as f:
            json.dump(data,f,indent=4)

        done = dealerDraw(channel)
        message = "The dealer draws a card."

        with open("resources/games/games.json", "r") as f:
            data = json.load(f)

    for user in data["blackjack games"][channel]["user hands"]:
        if data["blackjack games"][channel]["user hands"][user]["hit"] == False:
            data["blackjack games"][channel]["user hands"][user]["standing"] = True

        if data["blackjack games"][channel]["user hands"][user]["standing"] == False:
            allStanding = False

            if calcHandValue(data["blackjack games"][channel]["user hands"][user]["hand"]) >= 21 or data["blackjack games"][channel]["user hands"][user]["doubled"]:
                data["blackjack games"][channel]["user hands"][user]["standing"] = True
            else:
                preAllStanding = False

        data["blackjack games"][channel]["user hands"][user]["hit"] = False

        if data["blackjack games"][channel]["user hands"][user]["split"]:
            if data["blackjack games"][channel]["user hands"][user]["other hand"]["hit"] == False:
                data["blackjack games"][channel]["user hands"][user]["other hand"]["standing"] = True

            if data["blackjack games"][channel]["user hands"][user]["other hand"]["standing"] == False:
                allStanding = False

                if calcHandValue(data["blackjack games"][channel]["user hands"][user]["other hand"]["hand"]) >= 21 or data["blackjack games"][channel]["user hands"][user]["other hand"]["doubled"]:
                    data["blackjack games"][channel]["user hands"][user]["other hand"]["standing"] = True
                else:
                    preAllStanding = False

            data["blackjack games"][channel]["user hands"][user]["other hand"]["hit"] = False

    if allStanding:
        data["blackjack games"][channel]["all standing"] = True
        with open("resources/games/games.json", "w") as f:
            json.dump(data,f,indent=4)
    else:
        with open("resources/games/games.json", "w") as f:
            json.dump(data,f,indent=4)

    blackjackDraw.drawImage(channel)

    if allStanding:
        if done == False:
            return message, True, done
        else:
            return "The dealer is done drawing cards", True, done
    elif preAllStanding:
        return "", True, done
    else:
        if data["blackjack games"][channel]["round"] == 1:
            firstRoundMessage = ". You can also double down with \"!blackjack double\" or split with \"!blackjack split\""
        else:
            firstRoundMessage = ""
        return "You have 30 seconds to either hit or stand with \"!blackjack hit\" or \"!blackjack stand\""+firstRoundMessage+". It's assumed you're standing if you don't make a choice.", False, done

# When players try to hit
def blackjackHit(channel,user,handNumber = 0):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)

    if data["blackjack games"][channel]["user hands"][user]["split"] == False:
        hand = data["blackjack games"][channel]["user hands"][user]
        otherHand = False
    else:
        if handNumber != 0:
            if handNumber == 1:
                hand = data["blackjack games"][channel]["user hands"][user]
                otherHand = False
            elif handNumber == 2:
                hand = data["blackjack games"][channel]["user hands"][user]["other hand"]
                otherHand = True
            else:
                logThis(user+" tried to hit without specifying which hand")
                return "You have to specify the hand you're hitting with."
        else:
            logThis(user+" tried to hit without specifying which hand")
            return "You have to specify the hand you're hitting with."
            
    if data["blackjack games"][channel]["round"] > 0:
        if hand["hit"] == False:
            if hand["standing"] == False:
                hand["hand"].append(drawCard())
                hand["hit"] = True

                handValue = calcHandValue(hand["hand"])
                
                if handValue > 21:
                    hand["busted"] = True
                
                if otherHand:
                    data["blackjack games"][channel]["user hands"][user]["other hand"] = hand
                else:
                    data["blackjack games"][channel]["user hands"][user] = hand

                with open("resources/games/games.json", "w") as f:
                    json.dump(data,f,indent=4)

                return "accept"            
            else:
                logThis(user+" is already standing")
                return "You can't hit when you're standing"
        else:
            logThis(user+" has already hit this round")
            return "You've already hit this round"
    else:
        logThis(user+" tried to hit on the 0th round")
        return "You can't hit before you see your cards"


# When players try to double down
def blackjackDouble(channel,user,handNumber = 0):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)
    
    if data["blackjack games"][channel]["user hands"][user]["split"] == False:
        hand = data["blackjack games"][channel]["user hands"][user]
        otherHand = False
        correctRound = 1
    else:
        if handNumber != 0:
            if handNumber == 1:
                hand = data["blackjack games"][channel]["user hands"][user]
                otherHand = False
            elif handNumber == 2:
                hand = data["blackjack games"][channel]["user hands"][user]["other hand"]
                otherHand = True
            else:
                logThis(user+" tried to double without specifying which hand")
                return "You have to specify the hand you're doubling down."
        else:
            logThis(user+" tried to double without specifying which hand")
            return "You have to specify the hand you're doubling down."
        correctRound = 2
    

    if data["blackjack games"][channel]["round"] > 0:
        if hand["hit"] == False:
            if hand["standing"] == False:
                if data["blackjack games"][channel]["round"] == correctRound:
                    bet = hand["bet"]
                    if money.checkBalance(user) >= bet:
                        money.addMoney(user,-1 * bet)
                        with open("resources/games/games.json", "r") as f:
                            data = json.load(f)

                        hand["hand"].append(drawCard())
                        hand["hit"] = True
                        hand["doubled"] = True
                        hand["bet"] += bet

                        handValue = calcHandValue(hand["hand"])

                        
                        if handValue > 21:
                            hand["busted"] = True
                        
                        if otherHand:
                            data["blackjack games"][channel]["user hands"][user]["other hand"] = hand
                        else:
                            data["blackjack games"][channel]["user hands"][user] = hand

                        with open("resources/games/games.json", "w") as f:
                            json.dump(data,f,indent=4)

                        return "Adding another "+str(bet)+" GwendoBucks to "+user+"'s bet and drawing another card."
                    else:
                        logThis(user+" doesn't have enough GwendoBucks")
                        return "You don't have enough GwendoBucks"   
                else:
                    logThis(user+" tried to double on round "+str(data["blackjack games"][channel]["round"]))
                    return "You can only double down on the first round"      
            else:
                logThis(user+" is already standing")
                return "You can't double when you're standing"
        else:
            logThis(user+" has already hit this round")
            return "You've already hit this round"
    else:
        logThis(user+" tried to double on the 0th round")
        return "You can't double down before you see your cards"

# When players try to stand
def blackjackStand(channel,user,handNumber = 0):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)

    hand = data["blackjack games"][channel]["user hands"][user]
    if data["blackjack games"][channel]["round"] > 0:
        if hand["hit"] == False:
            if hand["standing"] == False:
                hand["standing"] = True
                with open("resources/games/games.json", "w") as f:
                    json.dump(data,f,indent=4)

                return "accept"  
            else:
                logThis(user+" is already standing")
                return "You're already standing"
        else:
            logThis(user+" has already hit this round")
            return "You've already hit this round"
    else:
        logThis(user+" tried to stand on the first round")
        return "You can't stand before you see your cards"

# When players try to split
def blackjackSplit(channel,user):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)

    if data["blackjack games"][channel]["round"] > 0:
        if data["blackjack games"][channel]["user hands"][user]["hit"] == False:
            if data["blackjack games"][channel]["user hands"][user]["standing"] == False:
                if data["blackjack games"][channel]["round"] == 1:
                    firstCard = calcHandValue([data["blackjack games"][channel]["user hands"][user]["hand"][0]])
                    secondCard = calcHandValue([data["blackjack games"][channel]["user hands"][user]["hand"][1]])
                    if firstCard == secondCard:
                        bet = data["blackjack games"][channel]["user hands"][user]["bet"]
                        if money.checkBalance(user) >= bet:
                            money.addMoney(user,-1 * bet)
                            with open("resources/games/games.json", "r") as f:
                                data = json.load(f)

                            
                            data["blackjack games"][channel]["user hands"][user]["hit"] = True
                            data["blackjack games"][channel]["user hands"][user]["other hand"]["hit"] = True
                            data["blackjack games"][channel]["user hands"][user]["split"] = True

                            data["blackjack games"][channel]["user hands"][user]["other hand"]["bet"] = data["blackjack games"][channel]["user hands"][user]["bet"]

                            data["blackjack games"][channel]["user hands"][user]["other hand"]["hand"].append(data["blackjack games"][channel]["user hands"][user]["hand"].pop(1))
                            data["blackjack games"][channel]["user hands"][user]["other hand"]["hand"].append(drawCard())
                            data["blackjack games"][channel]["user hands"][user]["hand"].append(drawCard())
                            
                            handValue = calcHandValue(data["blackjack games"][channel]["user hands"][user]["hand"])
                            otherHandValue = calcHandValue(data["blackjack games"][channel]["user hands"][user]["other hand"]["hand"])
                            if handValue > 21:
                                data["blackjack games"][channel]["user hands"][user]["busted"] = True
                            elif handValue == 21:
                                data["blackjack games"][channel]["user hands"][user]["blackjack"] = True
                            
                            if otherHandValue > 21:
                                data["blackjack games"][channel]["user hands"][user]["other hand"]["busted"] = True
                            elif otherHandValue == 21:
                                data["blackjack games"][channel]["user hands"][user]["other hand"]["blackjack"] = True
                            

                            with open("resources/games/games.json", "w") as f:
                                json.dump(data,f,indent=4)

                            return "Splitting "+user+"'s hand into 2. Adding their original bet to the second hand. You can use \"!Blackjack hit/stand/double 1\" and \"!Blackjack hit/stand/double 2\" to play the different hands."  
                        else:
                            logThis(user+" doesn't have enough GwendoBucks")
                            return "You don't have enough GwendoBucks"
                    else:
                        logThis(user+" tried to split 2 different cards")
                        return "Your cards need to have the same value to split"   
                else:
                    logThis(user+" tried to split on round "+data["blackjack games"][channel]["round"])
                    return "You can only split on the first round"      
            else:
                logThis(user+" is already standing")
                return "You can't split when you're standing"
        else:
            logThis(user+" has already hit this round")
            return "You've already hit this round"
    else:
        logThis(user+" tried to split on the 0th round")
        return "You can't split before you see your cards"

# Player enters the game and draws a hand
def blackjackPlayerDrawHand(channel,user,bet):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)

    logThis(user+" is trying to join the game in "+channel)
    
    if channel in data["blackjack games"]:
        if user not in data["blackjack games"][channel]["user hands"]:
            if len(data["blackjack games"][channel]["user hands"]) < 5:
                if data["blackjack games"][channel]["round"] == 0:
                    if bet >= 0:
                        if money.checkBalance(user) >= bet:
                            money.addMoney(user,-1 * bet)
                            playerHand = [drawCard(),drawCard()]

                            handValue = calcHandValue(playerHand)

                            with open("resources/games/games.json", "r") as f:
                                data = json.load(f)

                            if handValue == 21:
                                data["blackjack games"][channel]["user hands"][user] = {"hand":playerHand,
                                    "bet":bet,"standing":False,"busted":False,"blackjack":True,"hit":True,
                                    "doubled":False,"split":False,"other hand":{
                                    "hand":[],"bet":0,"standing":False,"busted":False,"blackjack":False,"hit":True,
                                    "doubled":False}}
                            else:
                                data["blackjack games"][channel]["user hands"][user] = {"hand":playerHand,
                                    "bet":bet,"standing":False,"busted":False,"blackjack":False,"hit":True,
                                    "doubled":False,"split":False,"other hand":{
                                    "hand":[],"bet":0,"standing":False,"busted":False,"blackjack":False,"hit":True,
                                    "doubled":False}}

                            with open("resources/games/games.json", "w") as f:
                                json.dump(data,f,indent=4)

                            logThis(user+" entered the game")
                            return user+" entered the game"
                        else:
                            logThis(user+" doesn't have enough GwendoBucks")
                            return "You don't have enough GwendoBucks to place that bet"
                    else:
                        logThis(user+" tried to bet a negative amount")
                        return "You can't bet a negative amount"
                else:
                    logThis("The table is no longer open for bets")
                    return "The table is no longer open for bets"
            else:
                logThis("There are already 5 players in the game.")
                return "There's already a maximum of players at the table."
        else:
            logThis(user+" is already in the game")
            return "You've already entered this game"
    else:
        logThis("There is no game going on in "+channel)
        return "There is no game going on in this channel"

# Starts a game of blackjack
def blackjackStart(channel:str):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)
    
    logThis("Trying to start a blackjack game in "+channel)

    if channel not in data["blackjack games"]:

        dealerHand = [drawCard(),drawCard()]

        data["blackjack games"][channel] = {"dealer hand": dealerHand,"dealer busted":False,"dealer blackjack":False,"user hands": {},"all standing":False,"round":0}
        
        if calcHandValue(dealerHand) == 21:
            data["blackjack games"][channel]["dealer blackjack"] = True
        
        with open("resources/games/games.json", "w") as f:
            json.dump(data,f,indent=4)

        copyfile("resources/games/blackjackTable.png","resources/games/blackjackTables/blackjackTable"+channel+".png")

        return "started"
    else:
        logThis("There is already a blackjack game going on in "+channel)
        return "There's already a blackjack game going on. Try again in a few minutes."

# Ends the game and calculates winnings
def blackjackFinish(channel):
    finalWinnings = "*Final Winnings:*\n"

    with open("resources/games/games.json", "r") as f:
        data = json.load(f)

    dealerValue = calcHandValue(data["blackjack games"][channel]["dealer hand"])
    reason = ""

    for user in data["blackjack games"][channel]["user hands"]:
        winnings = -1 * data["blackjack games"][channel]["user hands"][user]["bet"]
        if data["blackjack games"][channel]["user hands"][user]["blackjack"] and data["blackjack games"][channel]["dealer blackjack"] == False:
            reason = "(blackjack)"
            winnings +=  math.floor(2.5 * data["blackjack games"][channel]["user hands"][user]["bet"])
        elif data["blackjack games"][channel]["dealer blackjack"]:
                reason += "(dealer blackjack)"
        elif data["blackjack games"][channel]["user hands"][user]["busted"]:
            reason = "(busted)" 
        else:
            if data["blackjack games"][channel]["dealer busted"]:
                reason = "(dealer busted)"
                winnings += 2 * data["blackjack games"][channel]["user hands"][user]["bet"]
            elif calcHandValue(data["blackjack games"][channel]["user hands"][user]["hand"]) > dealerValue:
                winnings += 2 * data["blackjack games"][channel]["user hands"][user]["bet"]
                reason = "(highest value)"
            elif calcHandValue(data["blackjack games"][channel]["user hands"][user]["hand"]) == dealerValue:
                reason = "(pushed)"
                winnings += data["blackjack games"][channel]["user hands"][user]["bet"]
            else:
                reason = "(highest value)"
            
        
        if data["blackjack games"][channel]["user hands"][user]["split"]:
            winnings -= data["blackjack games"][channel]["user hands"][user]["other hand"]["bet"]
            if data["blackjack games"][channel]["user hands"][user]["other hand"]["blackjack"] and data["blackjack games"][channel]["dealer blackjack"] == False:
                reason += "(blackjack)"
                winnings +=  math.floor(2.5 * data["blackjack games"][channel]["user hands"][user]["other hand"]["bet"])
            elif data["blackjack games"][channel]["dealer blackjack"]:
                reason += "(dealer blackjack)"
            elif data["blackjack games"][channel]["user hands"][user]["busted"]:
                reason = "(busted)" 
            else:  
                if data["blackjack games"][channel]["dealer busted"]:
                    reason += "(dealer busted)"
                    winnings += 2 * data["blackjack games"][channel]["user hands"][user]["other hand"]["bet"]
                elif calcHandValue(data["blackjack games"][channel]["user hands"][user]["other hand"]["hand"]) > dealerValue:
                    reason += "(highest value)"
                    winnings += 2 * data["blackjack games"][channel]["user hands"][user]["other hand"]["bet"]
                elif calcHandValue(data["blackjack games"][channel]["user hands"][user]["other hand"]["hand"]) == dealerValue:
                    reason += "(pushed)"
                    winnings += data["blackjack games"][channel]["user hands"][user]["other hand"]["bet"]
                else:
                    reason += "(highest value)"
                


        if winnings < 0:
            if winnings == -1:
                finalWinnings += user+" lost "+str(-1 * winnings)+" GwendoBuck "+reason+"\n"
            else:
                finalWinnings += user+" lost "+str(-1 * winnings)+" GwendoBucks "+reason+"\n"
        else:
            if winnings == 1:
                finalWinnings += user+" won "+str(winnings)+" GwendoBuck "+reason+"\n"
            else:
                finalWinnings += user+" won "+str(winnings)+" GwendoBucks "+reason+"\n"
        
        netWinnings = winnings + data["blackjack games"][channel]["user hands"][user]["bet"] + data["blackjack games"][channel]["user hands"][user]["other hand"]["bet"]

        money.addMoney(user,netWinnings)

    with open("resources/games/games.json", "r") as f:
        data = json.load(f)

    del data["blackjack games"][channel]

    with open("resources/games/games.json", "w") as f:
        json.dump(data,f,indent=4)

    return finalWinnings
