import SwiftUI

/** Outside of the struct since it doesn't depend on generic */
enum SettingsRowInfoButtonStyle {
    case none
    case shownWithAction(_ action: () -> Void)
}

struct SettingsRow<TrailingView: View>: View {
    enum Style {
        case `default`
        case destructive

        var color: Color {
            switch self {
            case .default: Color.SemanticV1.textPrimary
            case .destructive: Color.SemanticV1.textWarning
            }
        }
    }

    let icon: Image
    let iconTrailingPadding: CGFloat
    let title: String
    let isLoading: Bool
    let infoButtonStyle: SettingsRowInfoButtonStyle
    let style: Style
    let trailingView: TrailingView
    let action: () -> Void

    init(
        icon: Image,
        iconTrailingPadding: CGFloat = 16.0,
        title: String,
        isLoading: Bool = false,
        infoButtonStyle: SettingsRowInfoButtonStyle = .none,
        style: Style = .default,
        @ViewBuilder trailingView: () -> TrailingView,
        action: @escaping () -> Void
    ) {
        self.icon = icon
        self.iconTrailingPadding = iconTrailingPadding
        self.title = title
        self.isLoading = isLoading
        self.infoButtonStyle = infoButtonStyle
        self.style = style
        self.trailingView = trailingView()
        self.action = action
    }

    var body: some View {
        Button(action: action) {
            HStack(spacing: .zero) {
                icon
                    .foregroundColor(style.color)
                    .padding(.trailing, iconTrailingPadding)

                Text(title)
                    .typographyV1(.body3)
                    .foregroundColor(style.color)
                    .padding(.trailing, 16.0)

                switch infoButtonStyle {
                case .none:
                    EmptyView()
                case .shownWithAction(let infoButtonAction):
                    Button {
                        infoButtonAction()
                    } label: {
                        Image.Icon.informationThick
                            .resizable()
                            .scaledToFit()
                            .frame(height: 20.0)
                            .foregroundColor(style.color)
                            .opacity(0.5)
                    }
                    .padding(.trailing, 8.0)
                }

                Spacer()

                trailingView
            }
            .opacity(isLoading ? 0 : 1)
            .padding(.vertical, 16)
            .padding(.horizontal, 8)
            .overlay(alignment: .center) {
                ProgressView()
                    .progressViewStyle(.circular)
                    .opacity(isLoading ? 1 : 0)
            }
        }
        .multilineTextAlignment(.center)
        .animation(.default, value: isLoading)

        Color.SemanticV1.backgroundTertiary
            .frame(height: 0.5)
            .padding(.horizontal, 8)
    }
}

extension SettingsRow where TrailingView == EmptyView {
    init(
        icon: Image,
        title: String,
        isLoading: Bool = false,
        style: Style = .default,
        action: @escaping () -> Void
    ) {
        self.init(
            icon: icon,
            title: title,
            isLoading: isLoading,
            style: style,
            trailingView: { EmptyView() },
            action: action
        )
    }
}
