//
//  AlertView.swift
//  PaiaiUIKit
//
//  Created by FFIB on 2017/11/14.
//  Copyright © 2017年 FFIB. All rights reserved.
//

import UIKit

public final class AlertView: UIView {

    public static var `default`: AlertView {
        return AlertView()
    }

    private typealias ItemAction = ((AlertItem) -> Void)

    private var confirmAction: AlertAction?
    private var cancelAction: AlertAction?

    public var cancelItem: AlertItem = {
        let item = AlertItem(type: .custom)
        item.backgroundColor = UIColor(r: 214, g: 214, b: 214)
        item.setTitleColor(UIColor(r: 51, g: 51, b: 51), for: .normal)

        return item
    }()

    public var confirmItem: AlertItem = {
        let item = AlertItem(type: .custom)
        item.backgroundColor = UIColor(r: 129, g: 209, b: 53)
        item.setTitleColor(UIColor.white, for: .normal)

        return item
    }()

    public var titleLabel: UILabel = {
        var label = UILabel()
        label.numberOfLines = 0
        label.textAlignment = .left
        label.backgroundColor = UIColor.white
        label.font = UIFont.systemFont(ofSize: 17)
        label.textColor = UIColor(r: 53, g: 53, b: 53)

        return label
    }()

    public var messageLabel: UILabel = {
        var label = UILabel()
        label.numberOfLines = 0
        label.textAlignment = .left
        label.backgroundColor = UIColor.white
        label.font = UIFont.systemFont(ofSize: 15)
        label.textColor = UIColor(r: 153, g: 153, b: 153)

        return label
    }()

    public var contentView: UIView?

    private var viewNotReady = true
    private var bottomView: UIView?
    private var topView: UIView?

    var title: String = "" {
        didSet {
            titleLabel.text = title
        }
    }
    var message: String = "" {
        didSet {
            messageLabel.text = message
        }
    }

    override public func didMoveToWindow() {
        super.didMoveToWindow()
        guard viewNotReady else { return }
        constructViewHierarchy()
        activateConstraints()
        installTarget()
        backgroundColor = UIColor.white
        viewNotReady = false
    }

    private func constructViewHierarchy() {
        if !title.isEmpty { addSubview(titleLabel) }
        if !message.isEmpty { addSubview(messageLabel) }
        if cancelAction != nil { addSubview(cancelItem) }
        if confirmAction != nil { addSubview(confirmItem) }
        if let contentView = contentView { addSubview(contentView) }
    }

    private func activateConstraints() {
        activateConstraintsItems()
        activateConstraintsLabels()
        activateConstraintsContentView()
        activateConstraintsRootView()
    }

    func addAlertAction(_ action: AlertAction) {
        switch action.style {
        case .default:
            confirmAction = action
        case .cancel:
            cancelAction = action
        case let .custom(item):
            confirmAction = action
            confirmItem = item
        }
    }

    private func installTarget() {
        if cancelAction != nil {
            cancelItem.addTarget(self, action: #selector(cancelAction(btn:)), for: .touchUpInside)
        }

        if confirmAction != nil {
            confirmItem.addTarget(self, action: #selector(confirmAction(btn:)), for: .touchUpInside)
        }
    }

    @objc private func confirmAction(btn: UIButton) {
        confirmAction?.handler?(confirmItem)

        dismissSuperViewController()
    }

    @objc private func cancelAction(btn: UIButton) {
        cancelAction?.handler?(cancelItem)

        dismissSuperViewController()
    }

    private func dismissSuperViewController() {
        guard let vc = getSuperViewController() else { return }
        vc.dismissController()
    }
}

/// MARK: layout
fileprivate extension AlertView {
    func activateConstraintsRootView() {
        guard let view = superview else { return }
        translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            centerYAnchor.constraint(equalTo: view.centerYAnchor),
            centerXAnchor.constraint(equalTo: view.centerXAnchor),
            leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40),
            trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40)
            ])

        if #available(iOS 11, *) {
            directionalLayoutMargins = NSDirectionalEdgeInsets(top: 10, leading: 16, bottom: 0, trailing: 16)
        } else {
            layoutMargins = UIEdgeInsets(top: 10, left: 16, bottom: 0, right: 16)
        }
        guard let topView = topView else { return }
        NSLayoutConstraint.activate([
            topView.bottomAnchor.constraint(equalTo: bottomView?.topAnchor ?? bottomAnchor, constant: -12)
            ])
    }

    func activateConstraintsContentView() {
        guard let contentView = contentView else { return }
        contentView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            contentView.leadingAnchor.constraint(equalTo: leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: trailingAnchor),
            contentView.topAnchor.constraint(equalTo: topView?.bottomAnchor ?? topAnchor),
            contentView.bottomAnchor.constraint(equalTo: bottomView?.bottomAnchor ?? bottomAnchor)
            ])

        bottomView = contentView
    }

    func activateConstraintsItems() {
        let (alertActions, items) = getActionsAndItems()
        guard !alertActions.isEmpty, let width = superview?.bounds.width else { return }

        /// center view spacing is 80
        /// margins 32
        let spacing: CGFloat = 80 + 32
        let itemSpacing: CGFloat = CGFloat((items.count - 1) * 6)
        let itemW = (width - spacing - itemSpacing) / CGFloat(items.count)

        var last: AlertItem?
        var leading: CGFloat = 0
        for (action, item) in zip(alertActions, items) {
            item.translatesAutoresizingMaskIntoConstraints = false
            item.setTitle(action.title, for: .normal)

            NSLayoutConstraint.activate([
                item.widthAnchor.constraint(equalToConstant: itemW),
                item.heightAnchor.constraint(equalToConstant: 36),
                item.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -14),
                item.leadingAnchor.constraint(equalTo: last?.trailingAnchor ?? layoutMarginsGuide.leadingAnchor,
                                              constant: leading)
                ])

            leading = 6
            last = item
        }
        bottomView = last
    }

    func activateConstraintsLabels() {
        var labels: [UILabel] = []
        if !title.isEmpty { labels.append(titleLabel) }
        if !message.isEmpty { labels.append(messageLabel) }
        if labels.isEmpty { return }

        var last: UILabel?

        for label in labels {
            label.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                label.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
                label.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
                label.topAnchor.constraint(equalTo: last?.bottomAnchor ?? layoutMarginsGuide.topAnchor, constant: 12)
                ])

            last = label
        }

        topView = last
    }
}

fileprivate extension AlertView {
    func getActionsAndItems() -> ([AlertAction], [AlertItem]) {
        let alertActions = [cancelAction, confirmAction].compactMap { $0 }
        let items = alertActions.map { (action) -> AlertItem in
            switch action.style {
            case .cancel:
                return cancelItem
            case .default, .custom:
                return confirmItem
            }
        }
        return (alertActions, items)
    }
}