//
//  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 v = superview else { return }
        translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            centerYAnchor.constraint(equalTo: v.centerYAnchor),
            centerXAnchor.constraint(equalTo: v.centerXAnchor),
            leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 40),
            trailingAnchor.constraint(equalTo: v.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 w = (width - spacing - itemSpacing) / CGFloat(items.count)
        
        var last: AlertItem? = nil
        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: w),
                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? = nil
        
        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)
    }
}