import SwiftUI
import AVFoundation

struct BaccaratGameView: View {
    @EnvironmentObject var gameState: GameState
    
    @State private var cardDealAudio: AVAudioPlayer?
    
    @State private var betIsZero = true
    @State private var bet = 0
    @State private var notEnoughMoney = false
    @State private var playing = false
    @State private var betPlayer = false
    @State private var betTie = false
    @State private var betBanker = false
    @State private var playerCards = ["Card Back", "Card Back", ""]
    @State private var currentPlayerCards = 2
    @State private var playerSum = 0
    @State private var bankerCards = ["Card Back", "Card Back", ""]
    @State private var currentBankerCards = 2
    @State private var bankerSum = 0
    @State private var gameFinished = false
    
    let cardSuites = ["Hearts", "Spades", "Diamonds", "Clubs"]
    let cardNames = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"]
    
    func initializeSounds() {
        guard let url = Bundle.main.url(forResource: "Card Deal SFX", withExtension: "mp3") else {
            return
        }
        
        cardDealAudio = try? AVAudioPlayer(contentsOf: url)
    }
    
    func generateRandomCard() -> String {
        return cardNames[Int.random(in: 0...12)] + " of " + cardSuites[Int.random(in: 0...3)]
    }
    
    func readCardValue(from string: String) -> Int {
        switch string.first {
        case "A":
            return 1
        case "2":
            return 2
        case "3":
            return 3
        case "4":
            return 4
        case "5":
            return 5
        case "6":
            return 6
        case "7":
            return 7
        case "8":
            return 8
        case "9":
            return 9
        case "1":
            return 10
        case "J":
            return 10
        case "Q":
            return 10
        case "K":
            return 10
        case .none:
            return -1
        default:
            return -1
        }
    }
    
    func dealCards () {
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(1)) {
            cardDealAudio?.play()
            playerCards[0] = generateRandomCard()
            playerSum = (playerSum + readCardValue(from: playerCards[0])) % 10
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(2)) {
            cardDealAudio?.play()
            bankerCards[0] = generateRandomCard()
            bankerSum = (bankerSum + readCardValue(from: bankerCards[0])) % 10
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(3)) {
            cardDealAudio?.play()
            playerCards[1] = generateRandomCard()
            playerSum = (playerSum + readCardValue(from: playerCards[1])) % 10
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(4)) {
            cardDealAudio?.play()
            bankerCards[1] = generateRandomCard()
            bankerSum = (bankerSum + readCardValue(from: bankerCards[1])) % 10
            
            if ((playerSum > 7) || (bankerSum > 7)) {
                checkWinner()
                return
            }
            
            if (playerSum < 6) {
                DispatchQueue.main.asyncAfter(deadline: .now() + Double(1)) {
                    cardDealAudio?.play()
                    currentPlayerCards += 1
                    playerCards[2] = generateRandomCard()
                    playerSum = (playerSum + readCardValue(from: playerCards[2])) % 10
                    
                    bankerDrawCardComplex(from: (readCardValue(from: playerCards[2]) % 10))
                }
            } else {
                bankerDrawCardNormal()
            }
        }
    }
    
    func bankerDrawCardNormal() {
        if (bankerSum < 6) {
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(1)) {
                cardDealAudio?.play()
                currentBankerCards += 1
                bankerCards[2] = generateRandomCard()
                bankerSum = (bankerSum + readCardValue(from: bankerCards[2])) % 10
                
                checkWinner()
            }
        } else {
            checkWinner()
        }
    }
    
    func bankerDrawCardComplex(from thirdPlayerCard: Int) {
        switch bankerSum {
        case 0...2:
            break
        case 3:
            if (thirdPlayerCard == 8) {
                checkWinner()
                return
            }
            break
        case 4:
            if ((thirdPlayerCard < 2) || (thirdPlayerCard > 7)) {
                checkWinner()
                return
            }
            break
        case 5:
            if ((thirdPlayerCard < 4) || (thirdPlayerCard > 7)) {
                checkWinner()
                return
            }
            break
        case 6:
            if ((thirdPlayerCard < 6) || (thirdPlayerCard > 7)) {
                checkWinner()
                return
            }
            break
        case 7...9:
            checkWinner()
            return
        default:
            return
        }
        
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(1)) {
            cardDealAudio?.play()
            currentBankerCards += 1
            bankerCards[2] = generateRandomCard()
            bankerSum = (bankerSum + readCardValue(from: bankerCards[2])) % 10
            
            checkWinner()
        }
    }
    
    func checkWinner() {
        gameFinished = true
        
        if (betPlayer && (playerSum > bankerSum)) {
            bet *= 2
            return
        }
        if (betBanker && (bankerSum > playerSum)) {
            bet = Int((Double(bet) * 1.95))
            return
        }
        if (bankerSum == playerSum) {
            if (betTie) {
                bet *= 8
            }
            
            return
        }
        
        bet *= 0
    }
    
    var body: some View {
        ZStack {
            Image("Baccarat Cloth")
                .resizable()
                .scaledToFill()
            
            VStack {
                Text("\n")
                
                Text("$\(gameState.money)")
                    .foregroundColor(.black)
                    .font(.system(.title, design: .rounded)).bold()
                    .padding(10)
                    .background(Color.yellow)
                    .cornerRadius(10)
                    .padding(.bottom, 50)
                
                HStack {
                    if (!playing) {
                        Image("Navy Blue Rectangle")
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: 100)
                            .cornerRadius(15)
                        Image("Navy Blue Rectangle")
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: 100)
                            .cornerRadius(15)
                    } else {
                        Image(playerCards[0])
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: 100)
                            .cornerRadius(15)
                        Image(playerCards[1])
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: 100)
                            .cornerRadius(15)
                        if (currentPlayerCards == 3) {
                            Image(playerCards[2])
                                .resizable()
                                .scaledToFit()
                                .frame(maxWidth: 100)
                                .cornerRadius(15)
                                .rotationEffect(.degrees(90))
                                .padding(.leading, 25)
                        }
                    }
                }
                
                if (!playing) {
                    Text("Player")
                        .multilineTextAlignment(.center)
                        .font(.system(.title2, design: .rounded)).bold()
                        .foregroundColor(.blue)
                } else {
                    Text("Player - \(playerSum)")
                        .multilineTextAlignment(.center)
                        .font(.system(.title2, design: .rounded)).bold()
                        .foregroundColor(.blue)
                }
                
                if (!playing) {
                    Text("\nBanker")
                        .multilineTextAlignment(.center)
                        .font(.system(.title2, design: .rounded)).bold()
                        .foregroundColor(.red)
                } else {
                    Text("\nBanker - \(bankerSum)")
                        .multilineTextAlignment(.center)
                        .font(.system(.title2, design: .rounded)).bold()
                        .foregroundColor(.red)
                }
                HStack {
                    if (!playing) {
                        Image("Maroon Rectangle")
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: 100)
                            .cornerRadius(15)
                        Image("Maroon Rectangle")
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: 100)
                            .cornerRadius(15)
                    } else {
                        Image(bankerCards[0])
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: 100)
                            .cornerRadius(15)
                        Image(bankerCards[1])
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: 100)
                            .cornerRadius(15)
                        if (currentBankerCards == 3) {
                            Image(bankerCards[2])
                                .resizable()
                                .scaledToFit()
                                .frame(maxWidth: 100)
                                .cornerRadius(15)
                                .rotationEffect(.degrees(90))
                                .padding(.leading, 25)
                        }
                    }
                }
                
                Text("\n")
                
                HStack {
                    if (!gameFinished) {
                        if (!playing) {
                            Button {
                                bet -= 20
                            } label: {
                                Text(" -  ")
                                    .foregroundColor(.white)
                                    .font(.system(.title3, design: .rounded)).bold()
                                    .padding(5)
                                    .background(Color.brown)
                                    .cornerRadius(15)
                            }
                            .disabled(betIsZero)
                        }
                        
                        Text("$\(bet)")
                            .foregroundColor(.white)
                            .font(.system(.title2, design: .rounded)).bold()
                        
                        if (!playing) {
                            Button {
                                bet += 20
                            } label: {
                                Text(" +  ")
                                    .foregroundColor(.white)
                                    .font(.system(.title3, design: .rounded)).bold()
                                    .padding(5)
                                    .background(Color.brown)
                                    .cornerRadius(15)
                            }
                            .disabled(notEnoughMoney)
                            
                            .onChange(of: bet) {
                                betIsZero = bet == 0
                                notEnoughMoney = (bet + 20) > gameState.money
                            }
                        }
                    } else {
                        if (bet > 0) {
                            if (betPlayer) {
                                Text("Player wins - You win +$\(bet)")
                                    .foregroundColor(.white)
                                    .font(.system(.title2, design: .rounded)).bold()
                            } else if (betBanker) {
                                Text("Banker wins - You win +$\(bet)")
                                    .foregroundColor(.white)
                                    .font(.system(.title2, design: .rounded)).bold()
                            } else {
                                Text("Tie - You win +$\(bet)")
                                    .foregroundColor(.white)
                                    .font(.system(.title2, design: .rounded)).bold()
                            }
                        } else {
                            if (betPlayer) {
                                Text("Banker wins - You lose")
                                    .foregroundColor(.white)
                                    .font(.system(.title2, design: .rounded)).bold()
                            } else if (betBanker) {
                                Text("Player wins - You lose")
                                    .foregroundColor(.white)
                                    .font(.system(.title2, design: .rounded)).bold()
                            } else {
                                Text("No tie - You lose")
                                    .foregroundColor(.white)
                                    .font(.system(.title2, design: .rounded)).bold()
                            }
                        }
                    }
                }
                
                Text("\n")
                
                HStack {
                    if (!gameFinished) {
                        Button {
                            playing = true
                            betPlayer = true
                            
                            gameState.money -= bet
                            
                            dealCards()
                        } label: {
                            Text("Player")
                                .foregroundColor(.black)
                                .font(.system(.title2, design: .rounded)).bold()
                                .padding(10)
                                .padding(.horizontal, 20)
                                .background(Color.blue)
                                .cornerRadius(20)
                        }
                        .disabled(playing || betIsZero)
                        Button {
                            playing = true
                            betTie = true
                            
                            gameState.money -= bet
                            
                            dealCards()
                        } label: {
                            Text("Tie")
                                .foregroundColor(.black)
                                .font(.system(.title2, design: .rounded)).bold()
                                .padding(10)
                                .padding(.horizontal, 20)
                                .background(Color.green)
                                .cornerRadius(20)
                        }
                        .disabled(playing || betIsZero)
                        Button {
                            playing = true
                            betBanker = true
                            
                            gameState.money -= bet
                            
                            dealCards()
                        } label: {
                            Text("Banker")
                                .foregroundColor(.black)
                                .font(.system(.title2, design: .rounded)).bold()
                                .padding(10)
                                .padding(.horizontal, 20)
                                .background(Color.red)
                                .cornerRadius(20)
                        }
                        .disabled(playing || betIsZero)
                    } else {
                        Button {
                            betIsZero = true
                            gameState.money += bet
                            
                            if (gameState.money < 20) {
                                notEnoughMoney = true
                            } else {
                                notEnoughMoney = false
                            }
                            
                            bet = 0
                            playing = false
                            betPlayer = false
                            betBanker = false
                            betTie = false
                            playerCards = ["Card Back", "Card Back", ""]
                            currentPlayerCards = 2
                            playerSum = 0
                            bankerCards = ["Card Back", "Card Back", ""]
                            currentBankerCards = 2
                            bankerSum = 0
                            gameFinished = false
                        } label: {
                            Text("Continue")
                                .foregroundColor(.black)
                                .font(.system(.title2, design: .rounded)).bold()
                                .padding(10)
                                .background(Color.red)
                                .cornerRadius(20)
                        }
                    }
                }
                
                Text("\n")
            }
        }
        .onDisappear() {
            cardDealAudio?.stop()
            cardDealAudio?.currentTime = 0
        }
        .onAppear() {
            if (gameState.money < 20) {
                notEnoughMoney = true
            } else {
                notEnoughMoney = false
            }
            
            initializeSounds()
        }
    }
}

#Preview {
    BaccaratGameView()
        .environmentObject(GameState())
}
