import SwiftUI

public struct TypingCycleView: View {
    public enum LabelStyle {
        case text
        case disabledTextEditor
    }

    private let emptyFieldText: String
    let labelStyle: LabelStyle
    let values: [String]
    let waitingTime: Double // Seconds for waiting
    let typingSpeed: Double // Seconds per character when typing
    let erasingSpeed: Double // Seconds per character when erasing

    @State private var currentIndex = 0
    @State private var displayedText = ""
    @State private var isTyping = true

    public init(
        labelStyle: LabelStyle,
        values: [String],
        waitingTime: Double = 2.0,
        typingSpeed: Double,
        erasingSpeed: Double
    ) {
        var reusedFirstLetter: String {
            if let firstPrompt = values.first, firstPrompt.count >= 1 {
                let firstLetter = String(firstPrompt.prefix(1))
                return values.reduce(firstLetter) { partialResult, current in
                    let firstLetter = String(current.prefix(1))
                    if partialResult == firstLetter {
                        return partialResult
                    } else {
                        return ""
                    }
                }
            } else {
                return ""
            }
        }

        self.emptyFieldText = reusedFirstLetter
        self.labelStyle = labelStyle
        self.values = values
        self.waitingTime = waitingTime
        self.typingSpeed = typingSpeed
        self.erasingSpeed = erasingSpeed
    }

    public var body: some View {
        ZStack {
            let textValue = displayedText.isEmpty ? emptyFieldText : displayedText
            switch labelStyle {
            case .text:
                Text(textValue)
            case .disabledTextEditor:
                TextEditor(text: .constant(textValue))
                    .disabled(true)
            }
        }
        .typographyV1(TypingCycleView.typography)
        .multilineTextAlignment(.leading)
        .task {
            /* Continuously cycle through the strings until task is cancelled on */
            while !Task.isCancelled {
                let currentString = values[currentIndex]
                if isTyping {
                    /* Type out the current string*/
                    for character in currentString {
                        displayedText.append(character)
                        try? await Task.sleep(nanoseconds: UInt64(typingSpeed * 1_000_000_000))
                    }

                    /* Pause briefly after typing the full string */
                    try? await Task.sleep(for: .seconds(waitingTime))

                    /* Switch to erasing */
                    isTyping = false

                } else {
                    /* Erase the current string */
                    while !displayedText.isEmpty {
                        displayedText.removeLast()
                        try? await Task.sleep(nanoseconds: UInt64(erasingSpeed * 1_000_000_000))
                    }

                    /* Move to the next string */
                    currentIndex = (currentIndex + 1) % values.count

                    /* Switch to typing the new string */
                    isTyping = true
                }
            }
        }
    }

    public static var typography: TypographyV1 {
        return .init(
            name: "Create Clip Text Placeholder",
            size: 24,
            style: .title,
            weight: .neueMontrealMedium,
            lineHeight: 32
        )
    }
}
