//
//  KMImageToolTipWindow.swift
//  PDF Reader Pro
//
//  Created by tangchao on 2023/11/23.
//

import Cocoa

class KMImageToolTipWindow: KMAnimatedBorderlessWindow {
    var context: KMImageToolTipContext?
    var point: NSPoint = .zero
    
    private let WINDOW_OFFSET           = 18.0
    private let ALPHA_VALUE             = 0.95
    private let CRITICAL_ALPHA_VALUE    = 0.9
    private let AUTO_HIDE_TIME_INTERVAL = 10.0
    private let DEFAULT_SHOW_DELAY      = 1.5
    private let ALT_SHOW_DELAY          = 0.2
    
    static let shared = KMImageToolTipWindow()
    
    deinit {
        KMPrint("KMImageToolTipWindow deinit.")
        
        NotificationCenter.default.removeObserver(self)
    }
    
    convenience init() {
        self.init(contentRect: .zero)
        
        self.hidesOnDeactivate = false
        self.ignoresMouseEvents = true
        self.isOpaque = true
        self.backgroundColor = .white
        self.hasShadow = true
        self.level = NSWindow.Level(104)
        self.defaultAlphaValue = ALPHA_VALUE
        self.autoHideTimeInterval = AUTO_HIDE_TIME_INTERVAL
        
        self.context = nil
        self.point = .zero
        
        NotificationCenter.default.addObserver(self, selector: #selector(orderOut), name: NSApplication.willResignActiveNotification, object: NSApp)
    }
    
    override func orderOut(_ sender: Any?) {
        self.point = .zero
        super.orderOut(sender)
    }
    
    override func fadeOut() {
        self.context = nil
        self.point = .zero
        super.fadeOut()
    }
    
    override func stopAnimation() {
        super.stopAnimation()
        
        Self.cancelPreviousPerformRequests(withTarget: self, selector: #selector(_showDelayed), object: nil)
    }
    
    // MARK: - Public Methods
    
    public func showForImageContext(_ aContext: KMImageToolTipContext, at aPoint: NSPoint) {
        if aContext != nil {
            if aContext.isEqual(self.context) == false {
                self.point = aPoint
                
                if aContext.isEqual(self.context) == false {
                    self.stopAnimation()
                    
                    self.context = aContext
                    
                    self.perform(#selector(_showDelayed), with: nil, afterDelay: self.isVisible ? ALT_SHOW_DELAY: DEFAULT_SHOW_DELAY)
                }
            }
        }
    }
    
    @objc func newShowForImageContext(_ aContext: KMImageToolTipContext, at aPoint: NSPoint) {
        self.point = aPoint
        
        if aContext.isEqual(self.context) == false {
            self.stopAnimation()
            
            self.context = aContext
            
            self.perform(#selector(_showDelayed), with: nil, afterDelay: self.isVisible ? ALT_SHOW_DELAY: DEFAULT_SHOW_DELAY)
        }
    }
}

// MARK: - Private Methods

extension KMImageToolTipWindow {
    @objc private func _showDelayed() {
        let thePoint = self.point == .zero ? NSEvent.mouseLocation : self.point
        var contentRect: NSRect = .zero
        let screenRect = NSScreen.screen(for: thePoint)?.frame ?? .zero
        let image = self.context?.toolTipImage()
        if (image != nil) {
            self.backgroundImage = image
                
            contentRect.size = image!.size
            contentRect.origin.x = fmin(thePoint.x, NSMaxX(screenRect) - NSWidth(contentRect))
            contentRect.origin.y = thePoint.y - WINDOW_OFFSET - NSHeight(contentRect)
            contentRect = self.frameRect(forContentRect: contentRect)
            if (NSMinY(contentRect) < NSMinX(screenRect)) {
                contentRect.origin.y = thePoint.y + WINDOW_OFFSET
            }
            self.setFrame(contentRect, display: false)
                
            if self.isVisible && self.alphaValue > CRITICAL_ALPHA_VALUE {
                self.orderFront(self)
            } else {
                self.fadeIn()
            }
        } else {
            self.fadeOut()
        }
    }
}