// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.

import SwiftUI
import Combine
import UIKit

public struct SessionTextField<ExplanationView>: View where ExplanationView: View {
    @Binding var text: String
    @Binding var error: String?
    @State var previousError: String = ""
    @State var textThemeColor: ThemeValue = .textPrimary
    
    let explanationView: () -> ExplanationView
    let placeholder: String
    let accessibility: Accessibility
    var isErrorMode: Bool {
        guard previousError.isEmpty else { return true }
        if error?.isEmpty == false { return true }
        return false
    }
    
    let height: CGFloat = isIPhone5OrSmaller ? CGFloat(48) : CGFloat(80)
    let cornerRadius: CGFloat = 13
    
    public init(
        _ text: Binding<String>,
        placeholder: String,
        error: Binding<String?>,
        accessibility: Accessibility = Accessibility(),
        @ViewBuilder explanationView: @escaping () -> ExplanationView = {
            EmptyView()
        }
    ) {
        self._text = text
        self.placeholder = placeholder
        self.accessibility = accessibility
        self._error = error
        self.explanationView = explanationView
        UITextView.appearance().backgroundColor = .clear
    }
    
    public var body: some View {
        VStack (
            alignment: .center,
            spacing: Values.smallSpacing
        ) {
            // Text input
            ZStack(alignment: .leading) {
                if text.isEmpty {
                    Text(placeholder)
                        .font(.system(size: Values.smallFontSize))
                        .foregroundColor(themeColor: isErrorMode ? .danger : .textSecondary)
                }
                
                if #available(iOS 16.0, *) {
                    SwiftUI.TextField(
                        "",
                        text: $text.onChange{ value in
                            if error?.isEmpty == false && text != value {
                                previousError = error!
                                error = nil
                            }
                        },
                        axis: .vertical
                    )
                    .font(.system(size: Values.smallFontSize))
                    .foregroundColor(themeColor: textThemeColor)
                    .accessibility(self.accessibility)
                } else {
                    ZStack {
                        TextEditor(
                            text: $text.onChange{ value in
                                if error?.isEmpty == false && text != value {
                                    previousError = error!
                                    error = nil
                                }
                            }
                        )
                        .font(.system(size: Values.smallFontSize))
                        .foregroundColor(themeColor: textThemeColor)
                        .textViewTransparentScrolling()
                        .accessibility(self.accessibility)
                        .frame(maxHeight: self.height)
                        .padding(.all, -4)
                        
                        // FIXME: This is a workaround for dynamic height of the TextEditor.
                        Text(text.isEmpty ? placeholder : text)
                            .font(.system(size: Values.smallFontSize))
                            .opacity(0)
                            .padding(.all, 4)
                            .frame(
                                maxWidth: .infinity,
                                maxHeight: self.height
                            )
                    }
                    .fixedSize(horizontal: false, vertical: true)
                }
            }
            .padding(.horizontal, Values.largeSpacing)
            .frame(maxWidth: .infinity)
            .frame(height: self.height)
            .overlay(
                RoundedRectangle(
                    cornerSize: CGSize(
                        width: self.cornerRadius,
                        height: self.cornerRadius
                    )
                )
                .stroke(themeColor: isErrorMode ? .danger : .borderSeparator)
            )
            .onReceive(Just(error)) { newValue in
                textThemeColor = (newValue?.isEmpty == false) ? .danger : .textPrimary
            }
            
            // Error message
            ZStack {
                if isErrorMode {
                    Text(error ?? previousError)
                        .bold()
                        .font(.system(size: Values.smallFontSize))
                        .foregroundColor(themeColor: .danger)
                        .multilineTextAlignment(.center)
                        .accessibility(
                            Accessibility(
                                identifier: "Error message",
                                label: error ?? previousError
                            )
                        )
                } else {
                    explanationView()
                }
            }
            .frame(
                height: 54,
                alignment: .top
            )
        }
    }
}

struct SessionTextField_Previews: PreviewProvider {
    @State static var text: String = "test"
    @State static var error: String? = "test error"
    @State static var emptyText: String = ""
    @State static var emptyError: String? = nil
    static var previews: some View {
        VStack {
            SessionTextField($text, placeholder: "Placeholder", error: $error) {}
            SessionTextField($emptyText, placeholder: "Placeholder", error: $emptyError) {}
        }
        
    }
}
