import Foundation
import UIKit
import Display
import TelegramCore
import SwiftSignalKit
import AsyncDisplayKit
import Postbox
import TelegramPresentationData
import PhotoResources

final class ThemeGridSearchItem: GridItem {
    let account: Account
    let theme: PresentationTheme
    let result: ChatContextResult
    let interaction: ThemeGridSearchInteraction
    
    let section: GridSection? = nil
    
    init(account: Account, theme: PresentationTheme, result: ChatContextResult, interaction: ThemeGridSearchInteraction) {
        self.account = account
        self.theme = theme
        self.result = result
        self.interaction = interaction
    }
    
    func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
        let node = ThemeGridSearchItemNode()
        node.setup(item: self)
        return node
    }
    
    func update(node: GridItemNode) {
        guard let node = node as? ThemeGridSearchItemNode else {
            assertionFailure()
            return
        }
        node.setup(item: self)
    }
}

final class ThemeGridSearchItemNode: GridItemNode {
    private let imageNode: TransformImageNode
    
    private(set) var item: ThemeGridSearchItem?
    private var currentDimensions: CGSize?
    
    override init() {
        self.imageNode = TransformImageNode()
        self.imageNode.contentAnimations = [.subsequentUpdates]
        self.imageNode.displaysAsynchronously = false
        
        super.init()
        
        self.addSubnode(self.imageNode)
    }
    
    override func didLoad() {
        super.didLoad()
        
        self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
    }
    
    func setup(item: ThemeGridSearchItem) {
        if self.item !== item {
            var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
            
            var thumbnailDimensions: CGSize?
            var thumbnailResource: TelegramMediaResource?
            var imageResource: TelegramMediaResource?
            var imageDimensions: CGSize?
            var immediateThumbnailData: Data?
            switch item.result {
            case let .externalReference(externalReference):
                if let content = externalReference.content, externalReference.type != "gif" {
                    imageResource = content.resource
                } else if let thumbnail = externalReference.thumbnail {
                    imageResource = thumbnail.resource
                }
                imageDimensions = externalReference.content?.dimensions?.cgSize
            case let .internalReference(internalReference):
                if let image = internalReference.image {
                    immediateThumbnailData = image.immediateThumbnailData
                    if let representation = imageRepresentationLargerThan(image.representations, size: PixelDimensions(width: 321, height: 321)) {
                        imageResource = representation.resource
                        imageDimensions = representation.dimensions.cgSize
                    }
                    if let file = internalReference.file {
                        if let thumbnailRepresentation = smallestImageRepresentation(file.previewRepresentations) {
                            thumbnailDimensions = thumbnailRepresentation.dimensions.cgSize
                            thumbnailResource = thumbnailRepresentation.resource
                        }
                    } else {
                        if let thumbnailRepresentation = smallestImageRepresentation(image.representations) {
                            thumbnailDimensions = thumbnailRepresentation.dimensions.cgSize
                            thumbnailResource = thumbnailRepresentation.resource
                        }
                    }
                } else if let file = internalReference.file {
                    immediateThumbnailData = file.immediateThumbnailData
                    if let dimensions = file.dimensions {
                        imageDimensions = dimensions.cgSize
                    } else if let largestRepresentation = largestImageRepresentation(file.previewRepresentations) {
                        imageDimensions = largestRepresentation.dimensions.cgSize
                    }
                    imageResource = smallestImageRepresentation(file.previewRepresentations)?.resource
                }
            }
            
            var representations: [TelegramMediaImageRepresentation] = []
            if let thumbnailResource = thumbnailResource, let thumbnailDimensions = thumbnailDimensions {
                representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailDimensions), resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
            }
            if let imageResource = imageResource, let imageDimensions = imageDimensions {
                representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(imageDimensions), resource: imageResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
            }
            if !representations.isEmpty {
                let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: [])
                updateImageSignal =  mediaGridMessagePhoto(account: item.account, userLocation: .other, photoReference: .standalone(media: tmpImage), fullRepresentationSize: CGSize(width: 512, height: 512))
            } else {
                updateImageSignal = .complete()
            }
            
            if let updateImageSignal = updateImageSignal {
                self.imageNode.setSignal(updateImageSignal)
            }
            
            self.currentDimensions = imageDimensions
            if let _ = imageDimensions {
                self.setNeedsLayout()
            }
        }
        
        self.item = item
    }
    
    @objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
        if case .ended = recognizer.state {
            if let item = self.item {
                item.interaction.openResult(item.result)
            }
        }
    }
    
    override func layout() {
        super.layout()
        
        let bounds = self.bounds
        self.imageNode.frame = bounds
        
        if let item = self.item, let dimensions = self.currentDimensions {
            let imageSize = dimensions.aspectFilled(bounds.size)
            self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: bounds.size, intrinsicInsets: UIEdgeInsets(), emptyColor: item.theme.list.mediaPlaceholderColor))()
        }
    }
}