import Foundation
import UIKit
import Display
import AsyncDisplayKit
import TelegramCore
import SwiftSignalKit
import StickerResources
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import ContextUI
import AccountContext

final class StickerPreviewPeekContent: PeekControllerContent {
    let context: AccountContext
    let item: ImportStickerPack.Sticker
    let menu: [ContextMenuItem]
    
    init(context: AccountContext, item: ImportStickerPack.Sticker, menu: [ContextMenuItem]) {
        self.context = context
        self.item = item
        self.menu = menu
    }
    
    func presentation() -> PeekControllerContentPresentation {
        return .freeform
    }
    
    func menuActivation() -> PeerControllerMenuActivation {
        return .press
    }
    
    func menuItems() -> [ContextMenuItem] {
        return self.menu
    }
    
    func node() -> PeekControllerContentNode & ASDisplayNode {
        return StickerPreviewPeekContentNode(account: self.context.account, item: self.item)
    }
    
    func topAccessoryNode() -> ASDisplayNode? {
        return nil
    }
    
    func fullScreenAccessoryNode(blurView: UIVisualEffectView) -> (PeekControllerAccessoryNode & ASDisplayNode)? {
        return nil
    }
    
    func isEqual(to: PeekControllerContent) -> Bool {
        if let to = to as? StickerPreviewPeekContent {
            return self.item === to.item
        } else {
            return false
        }
    }
}

private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekControllerContentNode {
    private let account: Account
    private let item: ImportStickerPack.Sticker
    
    private var textNode: ASTextNode
    private var imageNode: ASImageNode
    private var animationNode: AnimatedStickerNode?
    
    private var containerLayout: (ContainerViewLayout, CGFloat)?
    
    private let _ready = Promise<Bool>()
    
    init(account: Account, item: ImportStickerPack.Sticker) {
        self.account = account
        self.item = item
        
        self.textNode = ASTextNode()
        self.imageNode = ASImageNode()
        self.imageNode.displaysAsynchronously = false
        switch item.content {
            case let .image(data):
                self.imageNode.image = UIImage(data: data)
            case .animation, .video:
                let animationNode = DefaultAnimatedStickerNodeImpl()
                self.animationNode = animationNode
                let dimensions = PixelDimensions(width: 512, height: 512)
                let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 400.0, height: 400.0))
                if let resource = item.resource {
                    var isVideo = false
                    if case .video = item.content {
                        isVideo = true
                    }
                    self.animationNode?.setup(source: AnimatedStickerResourceSource(account: account, resource: resource._asResource(), isVideo: isVideo), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
                }
                self.animationNode?.visibility = true
        }
        if case let .image(data) = item.content, let image = UIImage(data: data) {
            self.imageNode.image = image
        }
        self.textNode.attributedText = NSAttributedString(string: item.emojis.joined(separator: " "), font: Font.regular(32.0), textColor: .black)
                
        super.init()
        
        self.isUserInteractionEnabled = false
        
        if let animationNode = self.animationNode {
            self.addSubnode(animationNode)
        } else {
            self.addSubnode(self.imageNode)
        }
        
        self.addSubnode(self.textNode)
        
        if let animationNode = self.animationNode {
            animationNode.started = { [weak self] in
                guard let strongSelf = self else {
                    return
                }
                strongSelf._ready.set(.single(true))
            }
        } else {
            self._ready.set(.single(true))
        }
    }
    
    func ready() -> Signal<Bool, NoError> {
        return self._ready.get()
    }

    func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
        let boundingSize = CGSize(width: 180.0, height: 180.0).fitted(size)
        let imageFrame = CGRect(origin: CGPoint(), size: boundingSize)
            
        let textSpacing: CGFloat = 10.0
        let textSize = self.textNode.measure(CGSize(width: 100.0, height: 100.0))
        self.textNode.frame = CGRect(origin: CGPoint(x: floor((imageFrame.size.width - textSize.width) / 2.0), y: -textSize.height - textSpacing), size: textSize)
        
        self.imageNode.frame = imageFrame
        
        if let animationNode = self.animationNode {
            animationNode.frame = imageFrame
            animationNode.updateLayout(size: imageFrame.size)
        }
        return boundingSize
    }
}