import SwiftUI

public struct NoResultsView<LeadingView: View, TrailingView: View>: View {
    public enum Style {
        case v1
        case v2

        var spacing: CGFloat {
            switch self {
            case .v1: return 24
            case .v2: return 0
            }
        }

        var titleTypography: TypographyV1 {
            switch self {
            case .v1: return .headline4
            case .v2: return .headline3
            }
        }

        var titleColor: Color {
            switch self {
            case .v1: return Color.SemanticV1.textSecondary
            case .v2: return Color.SemanticV1.textPrimary
            }
        }

        var messageTypography: TypographyV1 {
            switch self {
            case .v1: return .headline5
            case .v2: return .body2
            }
        }

        var messageColor: Color {
            switch self {
            case .v1: return Color.SemanticV1.textTertiary
            case .v2: return Color.SemanticV1.textSecondary
            }
        }
    }

    private let leadingView: LeadingView
    private let title: String?
    private let message: String
    private let style: Style
    private let detailMessage: AttributedString?
    private let trailingView: TrailingView
    private let horizontalPadding: CGFloat
    private let verticalPadding: CGFloat
    private let verticalSpacing: CGFloat?

    public init(
        @ViewBuilder leadingView: () -> LeadingView = { EmptyView() },
        title: String? = nil,
        message: String,
        style: Style = .v1,
        detailMesasge: AttributedString? = nil,
        @ViewBuilder trailingView: () -> TrailingView = { EmptyView() },
        horizontalPadding: CGFloat = 34,
        verticalPadding: CGFloat = 34,
        verticalSpacing: CGFloat? = nil
    ) {
        self.leadingView = leadingView()
        self.title = title
        self.message = message
        self.style = style
        self.detailMessage = detailMesasge
        self.trailingView = trailingView()
        self.horizontalPadding = horizontalPadding
        self.verticalPadding = verticalPadding
        self.verticalSpacing = verticalSpacing
    }

    public var body: some View {
        VStack(alignment: .center, spacing: verticalSpacing ?? style.spacing) {
            Spacer()

            leadingView

            if let title = title, !title.isEmpty {
                Text(title)
                    .typographyV1(style.titleTypography)
                    .foregroundColor(style.titleColor)
            }

            Text(message)
                .multilineTextAlignment(.center)
                .foregroundStyle(style.messageColor)
                .typographyV1(style.messageTypography)
                .lineLimit(10)
                .fixedSize(horizontal: false, vertical: true)

            if let detailMessage {
                Text(detailMessage)
                    .multilineTextAlignment(.center)
                    .foregroundStyle(style.messageColor)
                    .typographyV1(style.messageTypography)
                    .lineLimit(10)
                    .fixedSize(horizontal: false, vertical: true)
            }

            trailingView

            Spacer()
        }
        .frame(maxWidth: .infinity, alignment: .center)
        .padding(.horizontal, horizontalPadding)
        .padding(.vertical, verticalPadding)
    }
}

public extension NoResultsView where LeadingView == EmptyView, TrailingView == EmptyView {
    init(title: String? = nil, message: String, style: Style = .v1, horizontalPadding: CGFloat = 34, verticalPadding: CGFloat = 34, verticalSpacing: CGFloat? = nil) {
        self.init(leadingView: { EmptyView() }, title: title, message: message, style: style, trailingView: { EmptyView() }, horizontalPadding: horizontalPadding, verticalPadding: verticalPadding, verticalSpacing: verticalSpacing)
    }
}

struct NoResultsView_Previews: PreviewProvider {
    static var previews: some View {
        NoResultsViewSample()
    }
}

struct NoResultsViewSample: View {
    var body: some View {
        VStack(spacing: 4) {
            NoResultsView(title: "Title", message: "Empty state message here")
            NoResultsView(
                title: "Title",
                message: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam commodo, massa in maximus varius, dui massa iaculis nisl, vel mattis elit eros id purus."
            )
        }
        .padding()
    }
}
