import Foundation
import UIKit
import Postbox
import AsyncDisplayKit
import Display
import TelegramCore
import SyncCore
import TelegramPresentationData
import AvatarNode
import AccountContext

private let avatarFont = avatarPlaceholderFont(size: 16.0)

final class ChatMessageAvatarAccessoryItem: ListViewAccessoryItem {
    private let context: AccountContext
    private let peerId: PeerId
    private let peer: Peer?
    private let messageReference: MessageReference?
    private let messageTimestamp: Int32
    private let forwardInfo: MessageForwardInfo?
    private let emptyColor: UIColor
    private let controllerInteraction: ChatControllerInteraction
    
    private let day: Int32
    
    init(context: AccountContext, peerId: PeerId, peer: Peer?, messageReference: MessageReference?, messageTimestamp: Int32, forwardInfo: MessageForwardInfo?, emptyColor: UIColor, controllerInteraction: ChatControllerInteraction) {
        self.context = context
        self.peerId = peerId
        self.peer = peer
        self.messageReference = messageReference
        self.messageTimestamp = messageTimestamp
        self.forwardInfo = forwardInfo
        self.emptyColor = emptyColor
        self.controllerInteraction = controllerInteraction
        
        var t: time_t = time_t(messageTimestamp)
        var timeinfo: tm = tm()
        gmtime_r(&t, &timeinfo)
        
        self.day = timeinfo.tm_mday
    }
    
    func isEqualToItem(_ other: ListViewAccessoryItem) -> Bool {
        if case let other as ChatMessageAvatarAccessoryItem = other {
            if other.peerId != self.peerId {
                return false
            }
            if self.day != other.day {
                return false
            }
            
            var effectiveTimestamp = self.messageTimestamp
            if let forwardInfo = self.forwardInfo, forwardInfo.flags.contains(.isImported) {
                effectiveTimestamp = forwardInfo.date
            }
            
            var effectiveOtherTimestamp = other.messageTimestamp
            if let otherForwardInfo = other.forwardInfo, otherForwardInfo.flags.contains(.isImported) {
                effectiveOtherTimestamp = otherForwardInfo.date
            }
            
            if abs(effectiveTimestamp - effectiveOtherTimestamp) >= 10 * 60 {
                return false
            }
            if let forwardInfo = self.forwardInfo, let otherForwardInfo = other.forwardInfo, forwardInfo.flags.contains(.isImported), otherForwardInfo.flags.contains(.isImported) {
                if (forwardInfo.authorSignature != nil) == (otherForwardInfo.authorSignature != nil) && (forwardInfo.author != nil) == (otherForwardInfo.author != nil) {
                    if let authorSignature = forwardInfo.authorSignature, let otherAuthorSignature = otherForwardInfo.authorSignature {
                        if authorSignature != otherAuthorSignature {
                            return false
                        }
                    } else if let authorId = forwardInfo.author?.id, let otherAuthorId = otherForwardInfo.author?.id {
                        if authorId != otherAuthorId {
                            return false
                        }
                    }
                } else {
                    return false
                }
            } else if let forwardInfo = self.forwardInfo, forwardInfo.flags.contains(.isImported) {
                return false
            } else if let otherForwardInfo = other.forwardInfo, otherForwardInfo.flags.contains(.isImported) {
                return false
            }
            return true
        } else {
            return false
        }
    }
    
    func node(synchronous: Bool) -> ListViewAccessoryItemNode {
        let node = ChatMessageAvatarAccessoryItemNode()
        node.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0))
        if let forwardInfo = self.forwardInfo, forwardInfo.flags.contains(.isImported) {
            if let author = forwardInfo.author {
                node.setPeer(context: self.context, theme: self.context.sharedContext.currentPresentationData.with({ $0 }).theme, synchronousLoad: synchronous, peer: author, authorOfMessage: self.messageReference, emptyColor: self.emptyColor, controllerInteraction: self.controllerInteraction)
            } else if let authorSignature = forwardInfo.authorSignature, !authorSignature.isEmpty {
                let components = authorSignature.components(separatedBy: " ")
                if !components.isEmpty, !components[0].hasPrefix("+") {
                    var letters: [String] = []
                    
                    letters.append(String(components[0][components[0].startIndex]))
                    if components.count > 1 {
                        letters.append(String(components[1][components[1].startIndex]))
                    }
                    
                    node.setCustomLetters(context: self.context, theme: self.context.sharedContext.currentPresentationData.with({ $0 }).theme, synchronousLoad: synchronous, letters: letters, emptyColor: self.emptyColor, controllerInteraction: self.controllerInteraction)
                } else {
                    node.setCustomLetters(context: self.context, theme: self.context.sharedContext.currentPresentationData.with({ $0 }).theme, synchronousLoad: synchronous, letters: [], emptyColor: self.emptyColor, controllerInteraction: self.controllerInteraction)
                }
            } else {
                node.setCustomLetters(context: self.context, theme: self.context.sharedContext.currentPresentationData.with({ $0 }).theme, synchronousLoad: synchronous, letters: [], emptyColor: self.emptyColor, controllerInteraction: self.controllerInteraction)
            }
        } else if let peer = self.peer {
            node.setPeer(context: self.context, theme: self.context.sharedContext.currentPresentationData.with({ $0 }).theme, synchronousLoad: synchronous, peer: peer, authorOfMessage: self.messageReference, emptyColor: self.emptyColor, controllerInteraction: self.controllerInteraction)
        }
        return node
    }
}

final class ChatMessageAvatarAccessoryItemNode: ListViewAccessoryItemNode {
    var controllerInteraction: ChatControllerInteraction?
    var peer: Peer?
    var messageId: MessageId?
    
    let containerNode: ContextControllerSourceNode
    let avatarNode: AvatarNode
    
    var contextActionIsEnabled: Bool = true {
        didSet {
            if self.contextActionIsEnabled != oldValue {
                self.containerNode.isGestureEnabled = self.contextActionIsEnabled
            }
        }
    }
    
    override init() {
        self.containerNode = ContextControllerSourceNode()
        self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0))
        
        self.avatarNode = AvatarNode(font: avatarFont)
        self.avatarNode.isLayerBacked = !smartInvertColorsEnabled()
        self.avatarNode.frame = self.containerNode.bounds
        self.avatarNode.isUserInteractionEnabled = false
        
        super.init()
        
        self.isLayerBacked = false
        
        self.addSubnode(self.containerNode)
        self.containerNode.addSubnode(self.avatarNode)
        
        self.containerNode.activated = { [weak self] gesture, _ in
            guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction, let peer = strongSelf.peer else {
                return
            }
            controllerInteraction.openPeerContextMenu(peer, strongSelf.messageId, strongSelf.containerNode, strongSelf.containerNode.bounds, gesture)
        }
    }
    
    func setCustomLetters(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, letters: [String], emptyColor: UIColor, controllerInteraction: ChatControllerInteraction) {
        self.controllerInteraction = controllerInteraction
        self.peer = nil
        
        self.contextActionIsEnabled = false
        
        self.avatarNode.setCustomLetters(letters, icon: !letters.isEmpty ? nil : .phone)
    }
    
    func setPeer(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, peer: Peer, authorOfMessage: MessageReference?, emptyColor: UIColor, controllerInteraction: ChatControllerInteraction) {
        self.controllerInteraction = controllerInteraction
        self.peer = peer
        if let messageReference = authorOfMessage, case let .message(m) = messageReference.content {
            self.messageId = m.id
        }
        
        self.contextActionIsEnabled = peer.smallProfileImage != nil
        
        var overrideImage: AvatarNodeImageOverride?
        if peer.isDeleted {
            overrideImage = .deletedIcon
        }
        self.avatarNode.setPeer(context: context, theme: theme, peer: peer, authorOfMessage: authorOfMessage, overrideImage: overrideImage, emptyColor: emptyColor, synchronousLoad: synchronousLoad, displayDimensions: CGSize(width: 38.0, height: 38.0))
    }
}