import Foundation
import UIKit
import Display
import AsyncDisplayKit
import CallsEmoji

private let labelFont = Font.regular(22.0)
private let animationNodesCount = 3

private class EmojiSlotNode: ASDisplayNode {
    var emoji: String = "" {
        didSet {
            self.node.attributedText = NSAttributedString(string: emoji, font: labelFont, textColor: .black)
            let _ = self.node.updateLayout(CGSize(width: 100.0, height: 100.0))
        }
    }
    
    private let maskNode: ASDisplayNode
    private let containerNode: ASDisplayNode
    private let node: ImmediateTextNode
    private let animationNodes: [ImmediateTextNode]
    
    override init() {
        self.maskNode = ASDisplayNode()
        self.containerNode = ASDisplayNode()
        self.node = ImmediateTextNode()
        self.animationNodes = (0 ..< animationNodesCount).map { _ in ImmediateTextNode() }
                    
        super.init()
        
        let maskLayer = CAGradientLayer()
        maskLayer.colors = [UIColor.clear.cgColor, UIColor.white.cgColor, UIColor.white.cgColor, UIColor.clear.cgColor]
        maskLayer.locations = [0.0, 0.2, 0.8, 1.0]
        maskLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
        maskLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
        self.maskNode.layer.mask = maskLayer
        
        self.addSubnode(self.maskNode)
        self.maskNode.addSubnode(self.containerNode)
        self.containerNode.addSubnode(self.node)
        self.animationNodes.forEach({ self.containerNode.addSubnode($0) })
    }
    
    func animateIn(duration: Double) {
        for node in self.animationNodes {
            node.attributedText = NSAttributedString(string: randomCallsEmoji(), font: labelFont, textColor: .black)
            let _ = node.updateLayout(CGSize(width: 100.0, height: 100.0))
        }
        self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: -self.containerNode.frame.height + self.bounds.height), to: CGPoint(), duration: duration, delay: 0.1, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
    }
    
    override func layout() {
        super.layout()
        
        let maskInset: CGFloat = 4.0
        let maskFrame = self.bounds.insetBy(dx: 0.0, dy: -maskInset)
        self.maskNode.frame = maskFrame
        self.maskNode.layer.mask?.frame = CGRect(origin: CGPoint(), size: maskFrame.size)
        
        let spacing: CGFloat = 2.0
        let containerSize = CGSize(width: self.bounds.width, height: self.bounds.height * CGFloat(animationNodesCount + 1) + spacing * CGFloat(animationNodesCount))
        self.containerNode.frame = CGRect(origin: CGPoint(x: 0.0, y: maskInset), size: containerSize)
        
        self.node.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
        var offset: CGFloat = self.bounds.height + spacing
        for node in self.animationNodes {
            node.frame = CGRect(origin: CGPoint(x: 0.0, y: offset), size: self.bounds.size)
            offset += self.bounds.height + spacing
        }
    }
}

final class CallControllerKeyButton: HighlightableButtonNode {
    private let containerNode: ASDisplayNode
    private let nodes: [EmojiSlotNode]
    
    var key: String = "" {
        didSet {
            var index = 0
            for emoji in self.key {
                guard index < 4 else {
                    return
                }
                self.nodes[index].emoji = String(emoji)
                index += 1
            }
        }
    }
    
    init() {
        self.containerNode = ASDisplayNode()
        self.nodes = (0 ..< 4).map { _ in EmojiSlotNode() }
       
        super.init(pointerStyle: nil)
        
        self.addSubnode(self.containerNode)
        self.nodes.forEach({ self.containerNode.addSubnode($0) })
    }
        
    func animateIn() {
        self.layoutIfNeeded()
        self.containerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
        
        var duration: Double = 0.75
        for node in self.nodes {
            node.animateIn(duration: duration)
            duration += 0.3
        }
    }
    
    override func measure(_ constrainedSize: CGSize) -> CGSize {
        return CGSize(width: 114.0, height: 26.0)
    }
    
    override func layout() {
        super.layout()
        
        self.containerNode.frame = self.bounds
        var index = 0
        let nodeSize = CGSize(width: 29.0, height: self.bounds.size.height)
        for node in self.nodes {
            node.frame = CGRect(origin: CGPoint(x: CGFloat(index) * nodeSize.width, y: 0.0), size: nodeSize)
            index += 1
        }
        self.nodes.forEach({ self.containerNode.addSubnode($0) })
    }
}