//
//  KMToolbarItemView.swift
//  PDF Reader Pro
//
//  Created by tangchao on 2023/10/24.
//

import Cocoa

enum KMToolbarItemViewSelectBackgroundType: Int {
    case none = 0
    case imageBox
}

class KMToolbarClickButton: NSButton {
    weak var clickObject: AnyObject?
}

extension NSControl.ImagePosition {
    static let imageExpandLeft: NSControl.ImagePosition = .init(rawValue: 100)!
}

private let KMPopOverClosedByWindowNotificationName = "KMPopOverClosedByWindowNotification"
extension KMToolbarItemView {
    public static let popOverClosedNotificationName = Notification.Name(KMPopOverClosedByWindowNotificationName)
}

@objcMembers class KMToolbarItemView: NSView {
    var menuFormRepresentation: NSMenuItem?
    
    private var _itemIdentifier: String?
    var itemIdentifier: String? {
        get {
            return self._itemIdentifier
        }
    }
    
    lazy var clickButton: KMToolbarClickButton = {
        let view = KMToolbarClickButton()
        view.bezelStyle = .regularSquare
        view.isBordered = false
        view.imagePosition = .imageOnly
        view.clickObject = self
        return view
    }()
    
    var isSelected = false {
        didSet {
            if self.itemIdentifier != KMToolbarDividerItemIdentifier {
                if (isSelected) {
                    if(self.image != nil && self.alternateImage != nil) {
                        if (self.selectedImage != nil) {
                            self.imageViewBtn.image = self.selectedImage!
                        } else {
                            self.imageViewBtn.image = self.alternateImage!
                        }
                    }
                    if (self.nameBtn.superview != nil) {
                        self.nameBtn.setTitleColor(color: Self.textSelectedColor)
                    }
                    if(self.needExpandAction) {
                        self.needExpandButton.image = NSImage(named: "KMImageNameUXIconBtnTriDownSel")
                    }
                } else {
                    if (self.needExpandAction) {
                        self.needExpandButton.image = NSImage(named: "KMImageNameUXIconBtnTriDownNor")
                    }
                    if (self.image != nil) {
                        self.imageViewBtn.image = self.image!
                    }
                    if (self.nameBtn.superview != nil) {
                        self.nameBtn.setTitleColor(color: Self.textNormalColor)
                    }
                }
                self._updateSelectBackground()
            }
        }
    }
    var unEnabled = false {
        didSet {
            self.clickButton.isEnabled = !self.unEnabled
            self.nameBtn.isEnabled = !self.unEnabled
            self.imageViewBtn.isEnabled = !self.unEnabled
            self.needExpandButton.isEnabled = !self.unEnabled
        }
    }
    var isShowCustomToolTip = false {
        didSet {
            if (self.isShowCustomToolTip) {
                self.clickButton.toolTip = ""
            }
        }
    }
    var boxImagePosition: NSControl.ImagePosition = .imageLeft {
        didSet {
            self._layoutView()
        }
    }
    
    var image: NSImage? {
        didSet {
            self.imageViewBtn.image = self.image
        }
    }
    var selectedImage: NSImage?
    var alternateImage: NSImage?
    
    var titleName: String? {
        didSet {
            self.nameBtn.title = self.titleName ?? " "
            self.nameBtn.setTitleColor(color: Self.textNormalColor)
        }
    }
    
    weak var target: AnyObject? {
        didSet {
            self.clickButton.target = self.target
        }
    }
    var btnAction: Selector? {
        didSet {
            self.clickButton.action = self.btnAction
        }
    }
    
    var needExpandAction = false
    var btnTag = 0 {
        didSet {
            self.clickButton.tag = self.btnTag
        }
    }
    
    var customizeView: NSView? {
        didSet {
            self._layoutView()
        }
    }
  
    var normalBackgroundColor: NSColor = .clear
    var selectedBackgroundColor: NSColor = KMAppearance.Status.selColor()
    var selectBackgroundType: KMToolbarItemViewSelectBackgroundType = .none
    
    lazy var imageViewBox: NSBox = {
        let view = NSBox()
        view.borderWidth = 0
        view.contentViewMargins = NSSize.zero
        view.boxType = .custom
        view.borderColor = .clear
        view.cornerRadius = 7.0
        return view
    }()
    private lazy var imageViewBtn: NSButton = {
        let view = NSButton()
        view.bezelStyle = .regularSquare
        view.isBordered = false
        view.imagePosition = .imageOnly
        return view
    }()
    private var nameBtn: NSButton = {
        let view = NSButton()
        view.bezelStyle = .regularSquare
        view.isBordered = false
        view.imagePosition = .imageOnly
        view.title = ""
        return view
    }()
    private var needExpandButton: NSButton = {
        let view = NSButton()
        view.bezelStyle = .regularSquare
        view.isBordered = false
        view.imagePosition = .imageOnly
        view.image = NSImage(named: "KMImageNameUXIconBtnTriDownNor")
        return view
    }()
    private var _popOver: NSPopover?
    var popOver: NSPopover? {
        get {
            return self._popOver
        }
        set {
            if self._popOver == nil || self._popOver!.isEqual(to: newValue) == false {
                self._popOver = newValue
                if (newValue != nil) {
                    self.layer?.backgroundColor = Self.selectedBackgroundColor.cgColor
                } else {
                    self._updateSelectBackground()
                }
            }
        }
    }
    
    private var _menuViewController: KMCustomButtonPopMenuViewController?
    private var _kNormalImage: NSImage?
    private var _originalHelpTip: String?
    
    deinit {
//        Swift.debugPrint("KMToolbarItemView deinit")
        NotificationCenter.default.removeObserver(self)
    }
    
    class var textFont: NSFont {
        get {
            .systemFont(ofSize: 12)
        }
    }
    
    class var textNormalColor: NSColor {
        get {
            KMAppearance.titleColor()
        }
    }
    
    class var textSelectedColor: NSColor {
        get {
            KMAppearance.titleColor()
        }
    }
     
    class var selectedBackgroundColor: NSColor {
        get {
            return KMAppearance.Status.selColor()
        }
    }
    
    class var normalBackgroundColor: NSColor {
        get {
            return .clear
        }
    }
    
    convenience init(itemIdentifier: String) {
        self.init()
        
        self._itemIdentifier = itemIdentifier
        self.boxImagePosition = .imageLeft
        self.wantsLayer = true
        self.layer?.cornerRadius = 5
        self.layer?.masksToBounds = true
        self.nameBtn.font = Self.textFont
        
        self._addTrackingArea()
        NotificationCenter.default.addObserver(self, selector: #selector(_windowClosedPop), name: KMToolbarItemView.popOverClosedNotificationName, object: nil)
    }
    
    convenience init(itemIdentifier: String, postition imagePositionImagePosition: NSControl.ImagePosition, withPopMenu popMenuViewController: KMCustomButtonPopMenuViewController?) {
        self.init()
        
        self.boxImagePosition = imagePositionImagePosition
        self._menuViewController = popMenuViewController
        self._itemIdentifier = itemIdentifier
        self.wantsLayer = true
        self.layer?.cornerRadius = 4
        self.layer?.masksToBounds = true
        self.nameBtn.font = Self.textFont
        
        self._addTrackingArea()
        self._layoutView()
        if (popMenuViewController != nil) {
            NotificationCenter.default.addObserver(self, selector: #selector(_windowClosedPop), name: KMToolbarItemView.popOverClosedNotificationName, object: nil)
        }
    }
    
    override func draw(_ dirtyRect: NSRect) {
        if (self.itemIdentifier == KMToolbarDividerItemIdentifier) {
            let context = NSGraphicsContext.current?.cgContext
            KMContextSaveGState(context)
            KMContextTranslateCTM(context, CGRectGetWidth(dirtyRect)/2.0, CGRectGetHeight(dirtyRect)/2.0-10)
            KMContextMoveToPoint(context, 0, 0)
            KMContextAddLineToPoint(context, 0, 20)
            KMContextSetStrokeColorWithColor(context, NSColor(red: 0, green: 0, blue: 0, alpha: 0.1).cgColor)
            KMContextStrokePath(context)
            KMContextRestoreGState(context)
        }
    }
    
    override var toolTip: String? {
        get {
            return self._originalHelpTip
        }
        set {
            self.clickButton.toolTip = newValue ?? ""
            self._originalHelpTip = self.clickButton.toolTip
            if(self.isShowCustomToolTip) {
                self.clickButton.toolTip = ""
            }
        }
    }
    
    override func mouseEntered(with event: NSEvent) {
        super.mouseEntered(with: event)
        
        guard let _window = self.window else {
            return
        }
        
        if (!_window.isKeyWindow) {
            return
        }
        if (self.itemIdentifier == KMToolbarDividerItemIdentifier || self.customizeView != nil || self.image == nil) {
            return
        }
        if self.unEnabled {
            return
        }
        if (!self.isSelected) {
            if self.selectBackgroundType == .none {
                self.layer?.backgroundColor = Self.selectedBackgroundColor.cgColor
            } else {
                self.imageViewBox.fillColor = Self.selectedBackgroundColor
            }
            
            if(self.image != nil && self.alternateImage != nil) {
                self._kNormalImage = self.image
                self.imageViewBtn.image = self.alternateImage
                if(self.nameBtn.superview != nil) {
                    self.nameBtn.setTitleColor(color: Self.textNormalColor)
                }
            }
        }
        if (self.needExpandAction) {
            // KMImageNameUXIconBtnTriDownSel
            self.needExpandButton.image = NSImage(named: "KMImageNameUXIconBtnTriDownNor")
            self._showPop(self)
        }else if (self.isShowCustomToolTip) {
            self.perform(#selector(_showHUDHint), with: nil, afterDelay: 0.1)
        }
    }
    
    override func mouseExited(with event: NSEvent) {
        super.mouseExited(with: event)
        
        if (!self.isSelected && !self.needExpandAction) {
            if self.selectBackgroundType == .none {
                self.layer?.backgroundColor = self.normalBackgroundColor.cgColor
            } else {
                self.imageViewBox.fillColor = self.normalBackgroundColor
            }
           
            if(self.image != nil && self.alternateImage != nil) {
                self.imageViewBtn.image = self._kNormalImage ?? self.image!
            }
        }

        if(self.needExpandAction && !self.isSelected) {
            if self.selectBackgroundType == .none {
                self.layer?.backgroundColor = self.normalBackgroundColor.cgColor
            } else {
                self.imageViewBox.fillColor = self.normalBackgroundColor
            }
            
            if(self.image != nil && self.alternateImage != nil) {
                self.imageViewBtn.image = self._kNormalImage ?? self.image!
            }
            
            self.needExpandButton.image = NSImage(named: "KMImageNameUXIconBtnTriDownNor")
        }
        
        guard let _window = self.window else {
            return
        }
        if (!_window.isKeyWindow) {
            return
        }
        
        if(self.nameBtn.superview != nil && !self.isSelected) {
            self.nameBtn.setTitleColor(color: Self.textNormalColor)
        }
        
        if (self.isShowCustomToolTip && !self.needExpandAction) {
            NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(_showHUDHint), object: nil)
            self._closePop()
        }
    }
    
    private func _updateSelectBackground() {
        if self.selectBackgroundType == .none {
            if self.isSelected {
                self.layer?.backgroundColor = Self.selectedBackgroundColor.cgColor
            } else {
                self.layer?.backgroundColor = self.normalBackgroundColor.cgColor
            }
        } else if self.selectBackgroundType == .imageBox {
            if self.isSelected {
                self.imageViewBox.fillColor = Self.selectedBackgroundColor
            } else {
                self.imageViewBox.fillColor = self.normalBackgroundColor
            }
        }
    }
    
//    override func updateLayer() {
//        super.updateLayer()
//
//        self.wantsLayer = true
//        self.layer?.backgroundColor = KMAppearance.Layout.l_2Color().cgColor
//    }
}

// MARK: - Private Methods

extension KMToolbarItemView {
    private func _addTrackingArea() {
        let trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .inVisibleRect, .activeInKeyWindow], owner: self)
        self.addTrackingArea(trackingArea)
    }
    
    private func _showPop(_ sender: NSView) {
        if (self._popOver != nil) {
            return
        }
        let menuViewController = KMCustomButtonPopMenuViewController()
        menuViewController.delegate = self
        menuViewController.dataSources = self
        self.popOver = NSPopover()
        self.popOver?.delegate = self
        self.popOver?.contentViewController = menuViewController
        self.popOver?.animates = false
        self.popOver?.behavior = .semitransient
        self.popOver?.contentSize = menuViewController.view.frame.size
        
        var sourcesRect = sender.bounds
        sourcesRect = sender.convert(sourcesRect, to: nil)
        sourcesRect.origin.y -= 20
        sourcesRect.size.height += 20
        self.window?.popover = self.popOver
        self.window?.sourcesRect = sourcesRect
        
        self.popOver?.show(relativeTo: CGRectInset(self.bounds, 0, 5), of: self, preferredEdge: .minY)
    }
    
    private func _closePop() {
        self.popOver?.close()
        self.popOver = nil
    }
    
    @objc private func _showHUDHint() {
        //    KMToolbarItemPopViewController *popViewController = [[[KMToolbarItemPopViewController alloc] init] autorelease];
        //    self.popOver = [[[NSPopover alloc] init] autorelease];
        //    self.popOver.contentViewController = popViewController;
        //    self.popOver.animates = NO;
        //    self.popOver.behavior = NSPopoverBehaviorSemitransient;
        //    self.popOver.backgroundColor = [KMAppearance KMBluegrey01Color];
        //
        //    self.popOver.contentSize = popViewController.view.frame.size;
        //    [popViewController updateWithHelpTip:self.originalHelpTip];
        //    [self.popOver showRelativeToRect:self.bounds ofView:self preferredEdge:NSRectEdgeMinY];
    }
    
    @objc private func _windowClosedPop(sender: Notification) {
        if let data = self._popOver?.isEqual(to: sender.object), data {
            self.popOver = nil
        }
    }
    
    private func _layoutView() {
        if self.nameBtn.superview != nil {
            self.nameBtn.removeFromSuperview()
        }
        if self.imageViewBox.superview != nil {
            self.imageViewBox.removeFromSuperview()
        }
        if self.imageViewBtn.superview != nil {
            self.imageViewBtn.removeFromSuperview()
        }
        
        if let view = self.customizeView {
            if view.superview != nil {
                view.removeFromSuperview()
            }
            self.addSubview(view)
            view.km_add_leading_constraint()
            view.km_add_trailing_constraint()
            view.km_add_centerY_constraint()
            view.km_add_width_constraint(constant: NSWidth(view.bounds))
            view.km_add_height_constraint(constant: NSHeight(view.bounds))
            return
        } else if (self.itemIdentifier == KMToolbarDividerItemIdentifier) {
            self.addSubview(self.imageViewBox)
            self.imageViewBox.km_add_inset_constraint(inset: NSEdgeInsetsZero)
            self.imageViewBox.km_add_width_constraint(constant: 8)
            return
        }
        
        let offset = 4.0
        let offsetY = 2.0
        let offsetX = 4.0
        if self.boxImagePosition == .imageOnly {
            self.addSubview(self.imageViewBox)
            self.imageViewBox.km_add_inset_constraint()
            
            self.imageViewBox.contentView?.addSubview(self.imageViewBtn)
            self.imageViewBtn.km_add_inset_constraint(equalTo: self.imageViewBox, inset: NSEdgeInsets(top: offsetY, left: offsetX, bottom: offsetY, right: offsetX))
        } else if (self.boxImagePosition == .imageLeft) {
            self.addSubview(self.imageViewBox)
            self.imageViewBox.km_add_leading_constraint()
            self.imageViewBox.km_add_top_constraint()
            self.imageViewBox.km_add_bottom_constraint()
            
            self.imageViewBox.contentView?.addSubview(self.imageViewBtn)
            self.imageViewBtn.km_add_inset_constraint(equalTo: self.imageViewBox, inset: NSEdgeInsets(top: offsetY, left: 2*offsetX-2, bottom: offsetY, right: 2))
            
            self.addSubview(self.nameBtn)
            self.nameBtn.km_add_centerY_constraint()
            self.nameBtn.km_add_leading_constraint(equalTo: self.imageViewBox, attribute: .trailing)
            if (self.needExpandAction) {
                self.nameBtn.km_add_right_constraint(constant: -2*offsetX-8)
            } else {
                self.nameBtn.km_add_right_constraint(constant: -2*offsetX)
            }
            
            if(self.needExpandAction) {
                self.needExpandButton.image = NSImage(named: "KMImageNameUXIconBtnTriDownNor")
                self.addSubview(self.needExpandButton)
                self.needExpandButton.km_add_centerY_constraint()
                self.needExpandButton.km_add_width_constraint(constant: 8)
                self.needExpandButton.km_add_right_constraint(constant: -offset)
            }
            
            self.layer?.cornerRadius = 6
        } else if (self.boxImagePosition == .imageExpandLeft) {
            self.addSubview(self.imageViewBox)
            self.imageViewBox.km_add_leading_constraint()
            self.imageViewBox.km_add_top_constraint()
            self.imageViewBox.km_add_bottom_constraint()

            self.imageViewBox.contentView?.addSubview(self.imageViewBtn)
            self.imageViewBtn.km_add_inset_constraint(equalTo: self.imageViewBox, inset: NSEdgeInsets(top: offsetY, left: offsetX, bottom: offsetY, right: 0))

            self.needExpandButton.image = NSImage(named: "KMImageNameUXIconBtnTriDownNor")
            self.addSubview(self.needExpandButton)
            self.needExpandButton.km_add_centerY_constraint()
            self.needExpandButton.km_add_width_constraint(constant: 8)
            self.needExpandButton.km_add_right_constraint(constant: -offset)

            self.addSubview(self.nameBtn)
            self.nameBtn.km_add_centerY_constraint()
            self.nameBtn.km_add_leading_constraint(equalTo: self.imageViewBox, attribute: .trailing)
            self.nameBtn.km_add_trailing_constraint(equalTo: self.needExpandButton, attribute: .leading)
        } else if (self.boxImagePosition == .imageAbove) {
            self.addSubview(self.nameBtn)
            self.nameBtn.alignment = .center
            self.nameBtn.mas_makeConstraints { make in
                make?.left.right().equalTo()(0)
                make?.width.greaterThanOrEqualTo()(32)
                make?.bottom.equalTo()(self.mas_bottom)?.offset()(0)
            }
//            self.nameBtn.km_add_leading_constraint()
//            self.nameBtn.km_add_trailing_constraint()
//            self.nameBtn.km_add_bottom_constraint()
            
            self.addSubview(self.imageViewBox)
            self.imageViewBox.km_add_top_constraint()
            self.imageViewBox.km_add_width_constraint(constant: 32)
            self.imageViewBox.km_add_centerX_constraint()
            self.imageViewBox.km_add_bottom_constraint(equalTo: self.nameBtn, attribute: .top, constant: 0)
        
            self.imageViewBox.contentView?.addSubview(self.imageViewBtn)
            self.imageViewBtn.km_add_inset_constraint(inset: .init(top: 0, left: offset, bottom: 0, right: offset))
        }
            
        self.imageViewBox.borderWidth = 1.0
        self.addSubview(self.clickButton)
        self.clickButton.km_add_inset_constraint()
    }
}

extension KMToolbarItemView: NSPopoverDelegate {
    func popoverDidClose(_ notification: Notification) {
        if let data = self.popOver?.isEqual(to: notification.object), data {
            self._closePop()
        }
    }
}

extension KMToolbarItemView: KMCustomButtonPopMenuViewControllerDelegate, KMCustomButtonPopMenuViewControllerDataSources {
    func customViewButtonPopDidSelectIndex(_ index: Int) {
        self._closePop()
        
//        if (self.itemIdentifier == KMToolbarPageEditPageRangeItemIdentifier) {
            if let items = self.menuFormRepresentation?.submenu?.items {
                let item = items[index]
                _ = item.target?.perform(item.action, with: item)
            }
//        }
    }
    
    func numberOfLine() -> Int {
//        if (self.itemIdentifier == KMToolbarPageEditPageRangeItemIdentifier) {
            if let items = self.menuFormRepresentation?.submenu?.items {
                return items.count
            }
//        }
        return 0
    }
    
    func stringForLine(at index: Int) -> String? {
//        if (self.itemIdentifier == KMToolbarPageEditPageRangeItemIdentifier) {
            if let items = self.menuFormRepresentation?.submenu?.items {
                return items[index].title
            }
//        }
        return nil
    }
    
    func needInsertSeperateLine(at index: Int) -> Bool {
        if let items = self.menuFormRepresentation?.submenu?.items {
            return items[index].isSeparatorItem
        }
        return false
    }
    
    func needHightLightLine(at index: Int) -> Bool {
        return false
    }
    
    func imageForLine(at index: Int) -> NSImage? {
        if let items = self.menuFormRepresentation?.submenu?.items {
            return items[index].image
        }
        return nil
    }
    
    func itemEnable(at index: Int) -> Bool {
        return true
    }
}