//
//  KMToolbarItemView.swift
//  Cisdem PDFMaster
//
//  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) ?? .imageLeft
}

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
        }
    }
    weak var pdfView: CPDFListView?

    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 let data = self.selectedImage {
                            self.imageViewBtn.image = data
                        } else {
                            if let data = self.alternateImage {
                                self.imageViewBtn.image = data
                            }
                        }
                    }
                    if (self.nameBtn.superview != nil) {
                        self.nameBtn.setTitleColor(color: Self.fetchTextSelectedColor())
                    }
                    if(self.needExpandAction) {
                        self.needExpandButton.image = NSImage(named: "KMImageNameUXIconBtnTriDownSel")
                    }
                } else {
                    if (self.needExpandAction) {
                        self.needExpandButton.image = NSImage(named: "KMImageNameUXIconBtnTriDownNor")
                    }
                    if let data = self.image {
                        self.imageViewBtn.image = data
                    }
                    if (self.nameBtn.superview != nil) {
                        self.nameBtn.setTitleColor(color: Self.fetchTextNormalColor())
                    }
                }
                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()
            
            self.itemWidth = self._calculateWidth()
        }
    }
    
    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.fetchTextNormalColor())
            
            self.itemWidth = self._calculateWidth()
        }
    }
    
    weak var target: AnyObject? {
        didSet {
            self.clickButton.target = self.target
        }
    }
    var btnAction: Selector? {
        didSet {
            self.clickButton.action = self.btnAction
        }
    }
    
    var needExpandAction = false {
        didSet {
            self.itemWidth = self._calculateWidth()
        }
    }
    var btnTag = 0 {
        didSet {
            self.clickButton.tag = self.btnTag
        }
    }
    
    var customizeView: NSView? {
        didSet {
            self._layoutView()
            
            self.itemWidth = self._calculateWidth()
        }
    }
  
    private var promptView_: NSView?
    var promptView: NSView? {
        get {
            return self.promptView_
        }
    }
    private var promptIdentifier_: String?
    var promptIdentifier: String? {
        get {
            return self.promptIdentifier_
        }
        set {
            if self.promptIdentifier_ != newValue {
                self.promptIdentifier_ = newValue
                
                if let data = KMDataManager.ud_object(forKey: newValue ?? "") as? Bool {
                    self.isShowPrompt = !data
                } else {
                    self.isShowPrompt = true
                }
            }
        }
    }
    
    private var isShowPrompt_: Bool = false
    var isShowPrompt: Bool {
        get {
            return self.isShowPrompt_
        }
        set {
            self.isShowPrompt_ = newValue
            self.promptView?.isHidden = !newValue
        }
    }
    
    var normalBackgroundColor: NSColor = .clear
    var selectedBackgroundColor: NSColor = KMAppearance.Status.selColor()
    var selectBackgroundType: KMToolbarItemViewSelectBackgroundType = .none
    
    var itemWidth: CGFloat = 0
    var itemHeight: CGFloat = 0
    var isPopToolTip = false
    private var area_: NSTrackingArea?
    
    static let kDividerWidth: CGFloat = 8
    static let kHSpace: CGFloat = 4
    static let kExpandWidth: CGFloat = 8
    static let kRightMargin: CGFloat = 4
    static let kImageAboveMinWidth: CGFloat = 32
    
    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
    }()
    lazy var imageViewBtn: NSButton = {
        let view = NSButton()
        view.bezelStyle = .regularSquare
        view.isBordered = false
        view.imagePosition = .imageOnly
        return view
    }()
    var nameBtn: NSButton = {
        let view = NSButton()
        view.bezelStyle = .regularSquare
        view.isBordered = false
        view.imagePosition = .imageOnly
        view.title = ""
        return view
    }()
    var needExpandButton: NSButton = {
        let view = NSButton()
        view.bezelStyle = .regularSquare
        view.isBordered = false
        view.imagePosition = .imageOnly
        view.image = NSImage(named: "KMImageNameUXIconBtnTriDownNor")
        return view
    }()
    
    private var _kNormalImage: NSImage?
    private var _originalHelpTip: String?
    
    deinit {
        if (self.area_ != nil) {
            self.removeTrackingArea(self.area_!)
            self.area_ = nil
        }
        NotificationCenter.default.removeObserver(self)
    }
    
    class var textFont: NSFont {
        get {
            .systemFont(ofSize: 12)
        }
    }
    
//    class var textNormalColor: NSColor {
//        get {
//            KMAppearance.titleColor()
//        }
//    }
    
    class func fetchTextNormalColor() -> NSColor {
        return KMAppearance.titleColor()
    }
    
    class func fetchTextSelectedColor() -> NSColor {
        return 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
        
        let promptV = NSView()
        self.promptView_ = promptV
        self.addSubview(promptV)
        promptV.wantsLayer = true
        promptV.layer?.cornerRadius = 3
        promptV.layer?.backgroundColor = NSColor(red: 1, green: 56/255.0, blue: 25/255.0, alpha: 1).cgColor
        
        self.isShowPrompt = false
    }
    
    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 updateTrackingAreas() {
        super.updateTrackingAreas()

        let areaBound = NSRect(x: 0, y: 5, width: self.bounds.size.width, height: self.bounds.size.height)
        if let _area = self.area_, _area.rect.isEmpty == false {
            if (_area.rect.equalTo(areaBound)) {
                return
            }
        }
        
        if (self.area_ != nil) {
            self.removeTrackingArea(self.area_!)
            self.area_ = nil
        }
        // inVisibleRect activeInKeyWindow
        self.area_ = NSTrackingArea(rect: areaBound, options: [.mouseEnteredAndExited,.mouseMoved, .activeAlways], owner: self)
        self.addTrackingArea(self.area_!)
    }
    
    override func mouseEntered(with event: NSEvent) {
        super.mouseEntered(with: event)
        
        if let data = self.window?.isKeyWindow, !data {
            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.fetchTextNormalColor())
                }
            }
        }
    }
    
    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")
        }
        
        if let data = self.window?.isKeyWindow, !data {
            return
        }
        
        if(self.nameBtn.superview != nil && !self.isSelected) {
            self.nameBtn.setTitleColor(color: Self.fetchTextNormalColor())
        }
    }
    
    public func calculateWidth() -> CGFloat {
        let iWidth = self._calculateWidth()
        return iWidth
    }
    
    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
                self.layer?.backgroundColor = self.normalBackgroundColor.cgColor
            }
        }
    }
    
    override func interfaceThemeDidChanged(_ appearance: NSAppearance.Name) {
        super.interfaceThemeDidChanged(appearance)
        
        self.nameBtn.setTitleColor(Self.fetchTextNormalColor())
    }
}

// MARK: - Private Methods

extension KMToolbarItemView {
    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.promptView, view.superview != nil {
            view.removeFromSuperview()
        }
        
        if let view = self.customizeView {
            if view.superview != nil {
                view.removeFromSuperview()
            }
            let iWidth = NSWidth(view.bounds)
            self.addSubview(view)
            view.km_add_leading_constraint()
            view.km_add_trailing_constraint()
            view.km_add_centerY_constraint()
            view.km_add_width_constraint(constant: iWidth)
            view.km_add_height_constraint(constant: NSHeight(view.bounds))
            self.itemHeight = 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: Self.kDividerWidth)
            self.itemHeight = 40
            return
        }
        
        let offset = Self.kRightMargin
        let offsetY: CGFloat = 2.0
        let offsetX = Self.kHSpace
        if self.boxImagePosition == .imageOnly {
            let iWidth = (self.imageViewBtn.image?.size ?? .zero).width + offsetX * 2
            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: 0, bottom: offsetY, right: 0))
            self.itemHeight = 24
        } 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-Self.kExpandWidth)
            } 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: Self.kExpandWidth)
                self.needExpandButton.km_add_right_constraint(constant: -offset)
            }
            
            self.layer?.cornerRadius = 6
            self.itemHeight = 24
        } 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: Self.kExpandWidth)
            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)
            self.itemHeight = 24
        } 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()(Self.kImageAboveMinWidth)
                make?.height.mas_equalTo()(14)
                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: Self.kImageAboveMinWidth)
            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.5, left: offset, bottom: 0, right: offset))
            self.itemHeight = 40
        }
            
        self.imageViewBox.borderWidth = 1.0
        self.addSubview(self.clickButton)
        self.clickButton.km_add_inset_constraint()
        
        if let view = self.promptView {
            self.addSubview(view)
        }
    }
    
    private func _calculateWidth() -> CGFloat {
        if let v = self.customizeView {
            return NSWidth(v.bounds)
        } else if self.itemIdentifier == KMToolbarDividerItemIdentifier {
            return Self.kDividerWidth
        } else {
            if self.boxImagePosition == .imageOnly {
                return (self.imageViewBtn.image?.size ?? .zero).width + Self.kHSpace * 2
            } else if self.boxImagePosition == .imageLeft {
                // Compress 98 = 28(4+20+4) + 62 + 8(4+4)
                var iWidth = (self.imageViewBtn.image?.size.width ?? 0) + Self.kHSpace * 2
                self.nameBtn.sizeToFit()
                iWidth += self.nameBtn.frame.size.width
                iWidth += (2 * Self.kHSpace)
                if self.needExpandAction {
                    iWidth += 8
                }
                return iWidth
            } else if self.boxImagePosition == .imageExpandLeft {
                // Security 87
                var iWidth = (self.imageViewBtn.image?.size.width ?? 0) + Self.kHSpace
                self.nameBtn.sizeToFit()
                iWidth += self.nameBtn.frame.size.width
                iWidth += Self.kExpandWidth
                iWidth += Self.kRightMargin
                
                return iWidth
            } else if self.boxImagePosition == .imageAbove {
                // Panel 33
                self.nameBtn.sizeToFit()
                let iWidth = NSWidth(self.nameBtn.bounds)
                return max(Self.kImageAboveMinWidth, iWidth)
            }
        }
        return 0
    }
    
    override func layout() {
        super.layout()
        
        if let view = self.promptView, view.superview != nil {
            let wh: CGFloat = 6
            let y: CGFloat = 3
            view.frame = NSMakeRect(NSWidth(self.bounds)-wh, NSHeight(self.bounds)-wh-y, wh, wh)
        }
    }
}