import Foundation
import UIKit
import AsyncDisplayKit

public enum AlertControllerThemeBackgroundType {
    case light
    case dark
}

public final class AlertControllerTheme: Equatable {
    public let backgroundType: ActionSheetControllerThemeBackgroundType
    public let backgroundColor: UIColor
    public let separatorColor: UIColor
    public let highlightedItemColor: UIColor
    public let primaryColor: UIColor
    public let secondaryColor: UIColor
    public let accentColor: UIColor
    public let contrastColor: UIColor
    public let destructiveColor: UIColor
    public let disabledColor: UIColor
    public let controlBorderColor: UIColor
    public let baseFontSize: CGFloat
    
    public init(backgroundType: ActionSheetControllerThemeBackgroundType, backgroundColor: UIColor, separatorColor: UIColor, highlightedItemColor: UIColor, primaryColor: UIColor, secondaryColor: UIColor, accentColor: UIColor, contrastColor: UIColor, destructiveColor: UIColor, disabledColor: UIColor, controlBorderColor: UIColor, baseFontSize: CGFloat) {
        self.backgroundType = backgroundType
        self.backgroundColor = backgroundColor
        self.separatorColor = separatorColor
        self.highlightedItemColor = highlightedItemColor
        self.primaryColor = primaryColor
        self.secondaryColor = secondaryColor
        self.accentColor = accentColor
        self.contrastColor = contrastColor
        self.destructiveColor = destructiveColor
        self.disabledColor = disabledColor
        self.controlBorderColor = controlBorderColor
        self.baseFontSize = baseFontSize
    }
    
    public static func ==(lhs: AlertControllerTheme, rhs: AlertControllerTheme) -> Bool {
        if lhs.backgroundType != rhs.backgroundType {
            return false
        }
        if lhs.backgroundColor != rhs.backgroundColor {
            return false
        }
        if lhs.separatorColor != rhs.separatorColor {
            return false
        }
        if lhs.highlightedItemColor != rhs.highlightedItemColor {
            return false
        }
        if lhs.primaryColor != rhs.primaryColor {
            return false
        }
        if lhs.secondaryColor != rhs.secondaryColor {
            return false
        }
        if lhs.accentColor != rhs.accentColor {
            return false
        }
        if lhs.destructiveColor != rhs.destructiveColor {
            return false
        }
        if lhs.disabledColor != rhs.disabledColor {
            return false
        }
        if lhs.baseFontSize != rhs.baseFontSize {
            return false
        }
        return true
    }
}

open class AlertController: ViewController, StandalonePresentableController, KeyShortcutResponder {
    private var controllerNode: AlertControllerNode {
        return self.displayNode as! AlertControllerNode
    }
    
    public var theme: AlertControllerTheme {
        didSet {
            if oldValue != self.theme {
                self.controllerNode.updateTheme(self.theme)
            }
        }
    }
    public let contentNode: AlertContentNode
    private let allowInputInset: Bool
    
    private weak var existingAlertController: AlertController?
    
    public var willDismiss: (() -> Void)?
    public var dismissed: ((Bool) -> Void)?
    
    public init(theme: AlertControllerTheme, contentNode: AlertContentNode, existingAlertController: AlertController? = nil, allowInputInset: Bool = true) {
        self.theme = theme
        self.contentNode = contentNode
        self.existingAlertController = existingAlertController
        self.allowInputInset = allowInputInset
        
        super.init(navigationBarPresentationData: nil)
        
        self.blocksBackgroundWhenInOverlay = true
        
        self.statusBar.statusBarStyle = .Ignore
    }
    
    required public init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private var isDismissed = false
    override open func loadDisplayNode() {
        self.displayNode = AlertControllerNode(contentNode: self.contentNode, theme: self.theme, allowInputInset: self.allowInputInset)
        self.displayNodeDidLoad()
        
        self.controllerNode.existingAlertControllerNode = self.existingAlertController?.controllerNode
        
        self.controllerNode.dismiss = { [weak self] in
            if let strongSelf = self, strongSelf.contentNode.dismissOnOutsideTap {
                strongSelf.willDismiss?()
                strongSelf.controllerNode.animateOut {
                    self?.dismissed?(true)
                    self?.isDismissed = true
                    self?.dismiss()
                }
            }
        }
    }
    
    override open func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        self.existingAlertController?.dismiss(completion: nil)
        self.existingAlertController = nil
        
        self.controllerNode.animateIn()
    }
    
    override open func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
        super.containerLayoutUpdated(layout, transition: transition)
        
        self.controllerNode.containerLayoutUpdated(layout, transition: transition)
    }
    
    override open func dismiss(completion: (() -> Void)? = nil) {
        if !self.isDismissed {
            self.isDismissed = true
            self.dismissed?(false)
        }
        self.presentingViewController?.dismiss(animated: false, completion: completion)
    }
    
    public func dismissAnimated() {
        self.controllerNode.animateOut { [weak self] in
            self?.dismiss()
        }
    }
    
    public var keyShortcuts: [KeyShortcut] {
        return [
            KeyShortcut(
                input: UIKeyCommand.inputEscape,
                modifiers: [],
                action: { [weak self] in
                    self?.dismissAnimated()
                }
            ),
            KeyShortcut(
                input: "W",
                modifiers: [.command],
                action: { [weak self] in
                    self?.dismissAnimated()
                }
            ),
            KeyShortcut(
                input: "\r",
                modifiers: [],
                action: { [weak self] in
                    self?.controllerNode.performHighlightedAction()
                }
            ),
            KeyShortcut(
                input: UIKeyCommand.inputUpArrow,
                modifiers: [],
                action: { [weak self] in
                    self?.controllerNode.decreaseHighlightedIndex()
                }
            ),
            KeyShortcut(
                input: UIKeyCommand.inputDownArrow,
                modifiers: [],
                action: { [weak self] in
                    self?.controllerNode.increaseHighlightedIndex()
                }
            )
        ]
    }
}