import SwiftUI

// MARK: Public
protocol UniversalInputSelectionElement: Identifiable, Equatable, Hashable {
    var icon: Image? { get }
    var text: String? { get }
}

public enum UniversalInputCollection {
    struct TextField<T: Hashable> {
        let prompt: String
        @Binding var text: String
        var focus: FocusState<T?>.Binding
        var fieldType: T
        let contentType: UITextContentType
        let keyboardType: UIKeyboardType
        let submitLabel: SubmitLabel
        let action: () -> Void
    }

    struct SecureField<T: Hashable> {
        let prompt: String
        @Binding var text: String
        var focus: FocusState<T?>.Binding
        var fieldType: T
        let submitLabel: SubmitLabel
        let action: () -> Void
    }
}

// MARK: Inputs implementations
extension UniversalInputCollection.TextField: View {
    var body: some View {
        TextField("", text: $text)
            .padding(.horizontal, 8)
            .focused(focus, equals: fieldType)
            .font(.body2)
            .foregroundColor(.Main.black)
            .autocorrectionDisabled(true)
            .autocapitalization(.none)
            .textContentType(contentType)
            .keyboardType(keyboardType)
            .submitLabel(submitLabel)
            .textSelection(.enabled)
            .onSubmit {
                action()
            }
            .modifier(UniversalInputModifier(
                prompt: prompt,
                focus: focus,
                fieldType: fieldType,
                isActive: isFilled
            ))
    }

    var isFilled: Bool {
        !text.isEmpty || focus.wrappedValue == fieldType
    }
}

extension UniversalInputCollection.SecureField: View {
    var body: some View {
        SecureField("", text: $text)
            .padding(.horizontal, 8)
            .focused(focus, equals: fieldType)
            .font(.body2)
            .foregroundColor(.Main.black)
            .autocorrectionDisabled(true)
            .autocapitalization(.none)
            .textContentType(.password)
            .keyboardType(.asciiCapable)
            .submitLabel(submitLabel)
            .textSelection(.disabled)
            .onSubmit {
                action()
            }
            .modifier(UniversalInputModifier(
                prompt: prompt,
                focus: focus,
                fieldType: fieldType,
                isActive: isFilled
            ))
    }

    var isFilled: Bool {
        !text.isEmpty || focus.wrappedValue == fieldType
    }
}

// MARK: Modifiers
private struct UniversalInputModifier<T: Hashable>: ViewModifier {
    let prompt: String
    var focus: FocusState<T?>.Binding
    var fieldType: T
    let isActive: Bool
    var promptBackground: Color?
    var isCentered: Bool?
    var customTapAction: (() -> Void)?

    func body(content: Content) -> some View {
        VStack(spacing: 0) {
            ZStack {
                HStack {
                    Text(isActive ? "" : prompt)
                        .font(.body2)
                        .foregroundColor(.Main.gray)
                        .padding(8)
                    Spacer()
                }
                content
                    .frame(height: 40)
            }
        }
            .frame(height: 40)
            .background {
                ZStack {
                    RoundedRectangle(cornerRadius: 4)
                        .foregroundColor(.Main.white)
                    RoundedRectangle(cornerRadius: 4)
                        .stroke(Color.Main.gray)
                }
            }
            .contentShape(Rectangle())
            .onTapGesture {
                if let customTapAction {
                    customTapAction()
                } else {
                    if focus.wrappedValue != fieldType {
                        focus.wrappedValue = fieldType
                    }
                }
            }
    }
}

// MARK: Validators
extension UniversalInputCollection {
    enum Validators {
        static func email(_ input: String) -> String? {
            if !input.isEmpty {
                let mailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
                if !NSPredicate(format: "SELF MATCHES %@", mailRegex).evaluate(with: input) {
                    return L10n.Validator.jid
                } else {
                    return nil
                }
            } else {
                return nil
            }
        }
    }
}
