
import Foundation
import SwiftUI

// MARK: - OTPKeyboard

public struct OTPKeyboard: View {
    // MARK: Lifecycle

    public init(value: Binding<String>, length: Int, content: AnyView? = nil, onChange: ((String) -> Void)? = nil, onClose: @escaping () -> Void) {
        self._value = value
        self.length = length
        self.content = content
        self.onChange = onChange
        self.onClose = onClose
    }

    // MARK: Public

    public var body: some View {
        return VStack {
            VStack {
                HStack(){
                    SwiftUI.Button(action: onClose) {
                        Image(systemName: "xmark")
                            .foregroundColor(Colors.text)
                    }
                    Spacer()
                }
                
                ZStack(alignment: .trailing) {
                    ValueView(value, valueLength: length).padding(.trailing, 12)
                    SwiftUI.Button(action: onClear) {
                        Image(systemName: "xmark.circle.fill")
                            .resizable()
                            .frame(width: 12, height: 12)
                            .foregroundColor(Colors.text)
                    }.offset(x: -12)
                }.frame(minWidth: 148, maxWidth: 180, minHeight: 40)
                    .background(Colors.card)
                    .clipShape(Capsule())
                    .padding(.bottom, Spacing.M)
            }

            content

            HStack {
                KeyboardButton("7", action: self.onPressKey)
                KeyboardButton("8", action: self.onPressKey)
                KeyboardButton("9", action: self.onPressKey)
            }

            HStack {
                KeyboardButton("4", action: self.onPressKey)
                KeyboardButton("5", action: self.onPressKey)
                KeyboardButton("6", action: self.onPressKey)
            }

            HStack {
                KeyboardButton("1", action: self.onPressKey)
                KeyboardButton("2", action: self.onPressKey)
                KeyboardButton("3", action: self.onPressKey)
            }

            HStack {
                KeyboardButton("", action: self.onPressKey).disabled(true).opacity(0)
                KeyboardButton("0", action: self.onPressKey)
                SwiftUI.Button(action: onPressBack) {
                    HStack {
                        Image(
                            systemName: "delete.backward"
                        ).foregroundColor(Colors.text)
                    }
                }.frame(maxWidth: .infinity, minHeight: 48)
                    .clipShape(RoundedRectangle(cornerRadius: 8))
            }
        }
        .background(Colors.background)
        .valueChanged(value: value) { otp in
            if onChange != nil {
                self.onChange!(otp)
            }
        }
    }

    public func buildContent(_ content: @escaping () -> AnyView) -> OTPKeyboard {
        var newSelf = self
        newSelf.content = content()
        return newSelf
    }

    // MARK: Internal

    @Binding var value: String
    var length: Int
    var content: AnyView?
    var onChange: ((String) -> Void)?
    var onClose: () -> Void

    func onPressKey(key: String) {
        if value.count < length {
            value.append(key)
        }
    }

    func onPressBack() {
        if !value.isEmpty {
            value.removeLast()
        }
    }

    func onClear() {
        value.removeAll()
    }
}

// MARK: - ValueView

private struct ValueView: View {
    // MARK: Lifecycle

    init(_ value: String, valueLength: Int) {
        self.value = value
        self.valueLength = valueLength
    }

    // MARK: Public

    public var body: some View {
        return HStack {
            ForEach(0 ..< valueLength, id: \.self) { i in
                if i < value.count {
                    Circle().foregroundColor(Colors.text).frame(width: 8, height: 8)
                } else {
                    Circle().foregroundColor(Colors.textSecondary).frame(width: 8, height: 8)
                }
            }
        }.frame(maxWidth: .infinity, minHeight: 40)
    }

    // MARK: Internal

    var value: String = ""
    var valueLength: Int
}
