//
//  ContentView.swift
//  CowsAndBulls
//
//  Created by pat on 11/20/22.
//

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack(spacing: 0) {
            HStack {
                TextField("Enter a guess…", text: $guess)
                    .onSubmit(submitGuess)
                Button("Go", action: submitGuess)
            }
            .padding()
            List(0..<guesses.count, id: \.self) { index in
                let guess = guesses[index]
                let shouldShowResult = (enableHardMode == false) || (enableHardMode && index == 0)
                HStack {
                    Text(guess)
                    Spacer()
                    if shouldShowResult {
                        let res = result(for: guess)
                        if res.first == "0" {
                            Text(result(for: guess))
                                .foregroundColor(.red)
                        } else if res.first == "4" {
                            Text(result(for: guess))
                                .foregroundColor(.green)
                        } else {
                            Text(result(for: guess))
                                .foregroundColor(.yellow)
                        }
                    }
                }
            }
            .listStyle(.sidebar)
            if showGuessCount {
                Text("Guesses: \(guesses.count)/\(maximumGuesses)")
                    .padding()
            }
        }
        .frame(width: 250)
        .frame(minHeight: 300)
        .navigationTitle("Cows and Bulls")
        .onAppear(perform: startNewGame)
        .onChange(of: answerLength) { _ in startNewGame() }
        .alert("You win!", isPresented: $isGameOver) {
            Button("Play Again", action: startNewGame)
        } message: {
            if guesses.count < 10 {
                Text("Congratulations!\n Score: \(guesses.count)")
            } else if guesses.count < 20 {
                Text("Almost sweaty.\n Score: \(guesses.count)")
            } else {
                Text("Get güd nüb!\n Score: \(guesses.count)")
            }
            
        }
        .alert("You lose!", isPresented: $isGameLost) {
            Button ("Play Again", action: startNewGame)
        } message: {
            Text("You are a big chungus. Have you tried sucking less?\n\nThe correct answer is \(answer).")
        }
        // Removed .touchBar modifier.
    }
    
    @State private var guesses: [String] = []
    @State private var guess = ""
    @State private var answer = ""
    @State private var isGameOver = false
    @State private var isGameLost = false
    
    @AppStorage("maximumGuesses") var maximumGuesses = 100
    @AppStorage("answerLength") private var answerLength = 4
    @AppStorage("enableHardMode") var enableHardMode = false
    @AppStorage("showGuessCount") var showGuessCount = false
    
    
    
    func submitGuess() {
        // 1. Validate current guess.
        //     1.1 all chars are unique
        guard !Set(guesses).contains(guess) else { return }
        guard Set(guess).count == answerLength else { return }
        //     1.2 length is 4
        guard guess.count == answerLength else { return }
        //     1.3 all chars are in 0...9
        let badCharacters = CharacterSet(charactersIn: "0123456789").inverted
        guard guess.rangeOfCharacter(from: badCharacters) == nil else { return }
        // 2. Add current guess to guesses array
        guesses.insert(guess, at: 0)
        // 3. If guess is answer, show "You win!" dialogue
        if result(for: guess).contains("\(answerLength)b") {
            isGameOver = true
        }
        if guess == answer {
            // Present a dialogue, popup, or some message.
        } else if guesses.count == maximumGuesses {
            isGameLost = true
        }
        // 4. Reset value in guess
        guess = ""
    }
    func result(for guess: String) -> String {
        // 1. Initialize bulls and cows to 0
        var bulls: Int = 0
        var cows: Int = 0
        // 2. Convert guess and answer to arrays
        let guessLetters = Array(guess)
        let answerLetters = Array(answer)
        // 3. Iterate across the array(guess)
        //     3.1) if guess item is answer item: bulls++
        //     3.2) else if guess item is in answer: cows++
        for (index, letter) in guessLetters.enumerated() {
            if letter == answerLetters[index] {
                bulls += 1
            } else if answerLetters.contains(letter) {
                cows += 1
            }
        }
        // 4. Return bulls and cows as "part of a string"(?).
        return "\(bulls)b \(cows)c"
    }
    func startNewGame() {
        guard answerLength >= 3 && answerLength <= 8 else { return }
        guess = ""
        guesses.removeAll() // `keepingCapacity: Bool` parameter maintains array capacity even while emptying it.
        answer = ""
        
        let shuffledNumbers: [Int] = (0...9).shuffled()
        for i in 0..<answerLength {
            answer.append(String(shuffledNumbers[i])) // Strings are mutable in Swift??
        }
    }
}

struct SettingsView: View {
    var body: some View {
        TabView {
            Form {
                TextField("Maximum guesses", value: $maximumGuesses, format: .number)
                    .help("The maximum number of answers you can submit. Changing this will immediately restart your game.")
                TextField ("Answer length", value: $answerLength, format: .number)
                    .help("The length of the number string to guess. Changing this will immediately restart your game.")
                
                if answerLength < 3 || answerLength > 8 {
                    Text("Must be between 3 and 8")
                        .foregroundColor(.red)
                }
            }
            .padding()
            .tabItem {
                Label("Game", systemImage: "number.circle")
            }
            
            Form {
                Toggle("Enable hard mode", isOn: $enableHardMode)
                    .help("Hard mode shows only the result for the most recent guess.")
                Toggle("Show guess count", isOn: $showGuessCount)
                    .help("Adds a footer below your guesses showing how many guessses you have made.")
            }
            .padding()
            .tabItem {
                Label("Advanced", systemImage: "gearshape.2")
            }
        }
        .frame(width: 400)
    }
    
    @AppStorage("maximumGuesses") var maximumGuesses = 100
    @AppStorage("answerLength") private var answerLength = 4
    @AppStorage("enableHardMode") var enableHardMode = false
    @AppStorage("showGuessCount") var showGuessCount = false
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}