//
//  KMToolbarView.swift
//  PDF Master
//
//  Created by tangchao on 2023/10/24.
//

import Cocoa

private let KMToolbarSpaceItemWidth = 30.0
private let KMToolbarLineItemWidth = 1.0
private let KMToolbarItemSpace = 8.0

@objc protocol KMToolbarViewDelegate: NSObjectProtocol {
    @objc optional func toolbar(_ toolbar: KMToolbarView, itemFor identifier: String) -> KMToolbarItemView
    
    @objc optional func toolbarAllowedItemIdentifiers(_ toolbar: KMToolbarView) -> [String]
    @objc optional func toolbarDefaultItemIdentifiers(_ toolbar: KMToolbarView) -> [String]
    
    @objc optional func toolbarLeftDefaultItemIdentifiers(_ toolbar: KMToolbarView) -> [String]
    @objc optional func toolbarRightDefaultItemIdentifiers(_ toolbar: KMToolbarView) -> [String]
}

@objcMembers class KMToolbarView: NSView {
    private var _toolbarIdentifier: String?
    var toolbarIdentifier: String? {
        get {
            return self._toolbarIdentifier
        }
    }
    
    private var _items: [KMToolbarItemView] = []
    var items: [KMToolbarItemView] {
        get {
            return self._items
        }
    }
    
    weak var delegate: KMToolbarViewDelegate?
    
    private var _visibleItems: [KMToolbarItemView] = []
    private var _invisibleItems: [KMToolbarItemView] = []
    private var _contentView: NSView?
    var contentView: NSView {
        get {
            if (self._contentView == nil) {
                self._contentView = NSView()
            }
            
            return self._contentView!
        }
    }
    lazy var moreButton: NSButton = {
        let _moreButton = NSButton()
        _moreButton.bezelStyle = .regularSquare
        _moreButton.isBordered = false
        _moreButton.font = .systemFont(ofSize: 20)
        _moreButton.title = " »"
        _moreButton.isHidden = true
        _moreButton.target = self
        _moreButton.action = #selector(_moreButtonAction)
        _moreButton.wantsLayer = true
        _moreButton.layer?.backgroundColor = NSColor(red: 223.0/255.0, green: 225.0/255.0, blue: 229.0/255.0, alpha: 1).cgColor
        return _moreButton
    }()
    
    private lazy var centerView: NSView = {
        let view = NSView()
        return view
    }()
    private lazy var leftView: NSView = {
        let view = NSView()
        view.wantsLayer = true
        view.layer?.backgroundColor = NSColor(red: 247/255.0, green: 248/255.0, blue: 250/255.0 , alpha: 1).cgColor
        return view
    }()
    
    private class KMToolbarView_rightView: NSView {}
    private lazy var rightView: NSView = {
        let view = KMToolbarView_rightView()
        view.wantsLayer = true
        view.layer?.backgroundColor = NSColor(red: 247/255.0, green: 248/255.0, blue: 250/255.0, alpha: 1).cgColor
        return view
    }()
    
    convenience init(identifier: String) {
        self.init()
        
        self._toolbarIdentifier = identifier
        self._addTrackingArea()
        
        NotificationCenter.default.addObserver(self, selector: #selector(toolbarCustomChangeNotification), name: KMToolbarCustomChangeNotification, object: nil)
    }
    
    deinit {
        Swift.debugPrint("KMToolbarView deinit")
        NotificationCenter.default.removeObserver(self)
    }
    
    // MARK: - Private Methods
    
    private func _addTrackingArea() {
        let trackingArea = NSTrackingArea(rect: self.bounds, options: [.inVisibleRect, .activeInKeyWindow, .mouseMoved], owner: self)
        self.addTrackingArea(trackingArea)
    }
    
    override func mouseMoved(with event: NSEvent) {
//        self.window?.mouseMoved(with: event)
        super.mouseMoved(with: event)
    }
    
    @objc private func _moreButtonAction() {
        let menu = NSMenu()
        for item in self._invisibleItems {
            if (item.itemIdentifier == KMToolbarDividerItemIdentifier) {
                menu.addItem(NSMenuItem.separator())
            } else if (item.menuFormRepresentation != nil) {
                menu.addItem(item.menuFormRepresentation!)
            }
        }
        menu.popUp(positioning: menu.items.first, at: NSMakePoint(CGRectGetMaxX(self.moreButton.frame), CGRectGetMaxY(self.moreButton.frame)-5), in: self)
    }
    
    private func _updateMainView() {
        if (self.centerView.superview == nil) {
            self.addSubview(self.centerView)
        }

        self._updateLeftView()
        self._updateRightView()
        
        self.centerView.mas_remakeConstraints { make in
            make?.right.equalTo()(0)
            make?.top.equalTo()(self.mas_top)?.offset()(0)
            make?.bottom.equalTo()(self.mas_bottom)?.offset()(0)
            make?.left.mas_equalTo()(0)
        }
        
        if(self.contentView.superview == nil) {
            self.centerView.addSubview(self.contentView)
            self.contentView.mas_makeConstraints { make in
                make?.centerX.equalTo()(0)
                make?.centerY.equalTo()(0)
            }
        }
        
        for item in self.items {
            item.removeFromSuperview()
        }
        self._items = []
        
        var posX = 0.0
        var items: [KMToolbarItemView] = []
        var itemIdentifiers = self.delegate?.toolbarDefaultItemIdentifiers?(self) ?? []
        var lastItem: KMToolbarItemView?
        for i in 0 ..< (itemIdentifiers.count-self._invisibleItems.count) {
            let itemIdentifier = itemIdentifiers[i]
//            if (![itemIdentifier isKindOfClass:[NSString class]]) {
//                return;
//            }
            var item: KMToolbarItemView?
            if itemIdentifier == KMToolbarDividerItemIdentifier {
                item = KMToolbarItemView(itemIdentifier: itemIdentifier, postition: .imageOnly, withPopMenu: nil)
            } else if itemIdentifier == KMNewToolbarSpaceItemIdentifier {
                item = KMToolbarItemView(itemIdentifier: itemIdentifier, postition: .imageOnly, withPopMenu: nil)
                item?.layer?.backgroundColor = .clear
                item?.imageViewBox.borderColor = .clear
                item?.layer?.cornerRadius = 0.0
            } else if let data = self.delegate?.toolbar?(self, itemFor: itemIdentifier) {
                item = data
            }
            if (item == nil) {
                continue
            }

            self.contentView.addSubview(item!)
            if (lastItem != nil) {
                if (i == itemIdentifiers.count - 1) {
                    item?.mas_makeConstraints({ make in
                        make?.top.bottom().equalTo()(0)
                        make?.left.equalTo()(lastItem!.mas_right)?.offset()(KMToolbarItemSpace)
                        make?.right.equalTo()(self.contentView.mas_right)?.offset()(0)
                    })
                } else {
                    item?.mas_makeConstraints({ make in
                        make?.top.bottom().equalTo()(0)
                        make?.left.equalTo()(lastItem!.mas_right)?.offset()(KMToolbarItemSpace)
                    })
                }
                
            } else {
                if (item?.image != nil) {
                    item?.mas_makeConstraints({ make in
                        make?.top.bottom().equalTo()(0)
                        make?.left.equalTo()(0)
                    })
                } else {
                    item?.mas_makeConstraints({ make in
                        make?.top.bottom().equalTo()(0)
                        make?.left.equalTo()(0)
                        make?.height.offset()(40)
                    })
                }
            }
            items.append(item!)
            lastItem = item
            posX += item!.frame.size.width
        }
        self._items = items
        
        self.addSubview(self.moreButton)
    }
    
    // UI 20 16
    // item w 28 h 24
    private func _updateView() {
        self._updateLeftView()
        self._updateRightView()
        
        if(self.contentView.superview == nil) {
            self.addSubview(self.contentView)
            self.contentView.mas_makeConstraints { make in
                make?.centerX.equalTo()(0)
                make?.centerY.equalTo()(0)
            }
        }
        
        for item in self.items {
            item.removeFromSuperview()
        }
        self._items = []
        
        var posX = 0.0
        var items: [KMToolbarItemView] = []
        var itemIdentifiers = self.delegate?.toolbarDefaultItemIdentifiers?(self) ?? []
        
        var lastItem: KMToolbarItemView?
        for i in 0 ..< (itemIdentifiers.count-self._invisibleItems.count) {
            let itemIdentifier = itemIdentifiers[i]
//            if (![itemIdentifier isKindOfClass:[NSString class]]) {
//                return;
//            }
            var item: KMToolbarItemView?
            if itemIdentifier == KMToolbarDividerItemIdentifier {
                item = KMToolbarItemView(itemIdentifier: itemIdentifier, postition: .imageOnly, withPopMenu: nil)
            } else if itemIdentifier == KMNewToolbarSpaceItemIdentifier {
                item = KMToolbarItemView(itemIdentifier: itemIdentifier, postition: .imageOnly, withPopMenu: nil)
                item?.layer?.backgroundColor = .clear
                item?.imageViewBox.borderColor = .clear
                item?.layer?.cornerRadius = 0.0
            } else if let data = self.delegate?.toolbar?(self, itemFor: itemIdentifier) {
                item = data
            }
            if (item == nil) {
                continue
            }

            self.contentView.addSubview(item!)
            if (lastItem != nil) {
                if (i == itemIdentifiers.count - 1) {
                    item?.mas_makeConstraints({ make in
                        make?.top.bottom().equalTo()(0)
                        make?.left.equalTo()(lastItem!.mas_right)?.offset()(KMToolbarItemSpace)
                        make?.right.equalTo()(self.contentView.mas_right)?.offset()(0)
                    })
                } else {
                    if itemIdentifier == KMNewToolbarSpaceItemIdentifier {
//                    if ([itemIdentifier isEqualToString:]) {
                        item?.mas_makeConstraints({ make in
                            make?.top.bottom().equalTo()(0)
                            make?.left.equalTo()(lastItem!.mas_right)?.offset()(2)
                        })
                    } else {
                        if lastItem?.itemIdentifier == KMNewToolbarSpaceItemIdentifier {
//                        if ([lastItem.itemIdentifier isEqualToString:]) {
                            item?.mas_makeConstraints({ make in
                                make?.top.bottom().equalTo()(0)
                                make?.left.equalTo()(lastItem!.mas_right)?.offset()(2)
                            })
                        } else {
                            item?.mas_makeConstraints({ make in
                                make?.top.bottom().equalTo()(0)
                                make?.left.equalTo()(lastItem!.mas_right)?.offset()(KMToolbarItemSpace)
                            })
                        }
                    }
                }
            } else {
                if (item?.image != nil) {
                    item?.mas_makeConstraints({ make in
                        make?.top.bottom().equalTo()(0)
                        make?.left.equalTo()(0)
                    })
                } else {
                    item?.mas_makeConstraints({ make in
                        make?.top.bottom().equalTo()(0)
                        make?.left.equalTo()(0)
                        make?.height.offset()(40)
                    })
                }
            }
            items.append(item!)
            lastItem = item
            posX += item!.frame.size.width
        }
        self._items = items;
        
        self.addSubview(self.moreButton)
    }
    
    private func _updateLeftView() {
        // 刷新前移除视图
        for item in self.leftView.subviews {
            item.removeFromSuperview()
        }
        if (self.leftView.superview != nil) {
            self.leftView.removeFromSuperview()
        }
        
        if let itemIdentifiers = self.delegate?.toolbarLeftDefaultItemIdentifiers?(self), itemIdentifiers.count > 0 {
            if (self.leftView.superview == nil) {
                self.addSubview(self.leftView)
                
                self.leftView.mas_makeConstraints { make in
                    make?.left.equalTo()(self.mas_left)?.offset()(0)
                    make?.top.equalTo()(self.mas_top)?.offset()(0)
                    make?.bottom.equalTo()(self.mas_bottom)?.offset()(0)
                }
            }
            
            var lastItem: KMToolbarItemView?
            for i in 0 ..< itemIdentifiers.count {
                let itemIdentifier = itemIdentifiers[i]
                var item: KMToolbarItemView?
                if itemIdentifier == KMToolbarDividerItemIdentifier {
                    item = KMToolbarItemView(itemIdentifier: itemIdentifier, postition: .imageOnly, withPopMenu: nil)
                } else if itemIdentifier == KMNewToolbarSpaceItemIdentifier {
                    item = KMToolbarItemView(itemIdentifier: itemIdentifier, postition: .imageOnly, withPopMenu: nil)
                    item?.layer?.backgroundColor = .clear
                    item?.imageViewBox.borderColor = .clear
                    item?.layer?.cornerRadius = 0.0
                } else if let data = self.delegate?.toolbar?(self, itemFor: itemIdentifier) {
                    item = data
                }
                if (item == nil) {
                    continue
                }
                
                self.leftView.addSubview(item!)
                if (lastItem != nil) {
                    if (i == itemIdentifiers.count - 1) {
                        item?.mas_makeConstraints({ make in
                            make?.top.equalTo()(0)
                            make?.bottom.equalTo()(0)
                            make?.left.equalTo()(lastItem!.mas_right)?.offset()(KMToolbarItemSpace)
                            make?.right.equalTo()(self.leftView.mas_right)?.offset()(0)
                        })
                    } else {
                        item?.mas_makeConstraints({ make in
                            make?.top.equalTo()(0)
                            make?.bottom.equalTo()(0)
                            make?.left.equalTo()(lastItem!.mas_right)?.offset()(KMToolbarItemSpace)
                        })
                    }
                    
                } else {
                    if (i == itemIdentifiers.count - 1) {
                        item?.mas_makeConstraints({ make in
                            make?.top.equalTo()(0)
                            make?.bottom.equalTo()(0)
                            make?.left.equalTo()(self.leftView.mas_left)?.offset()(KMToolbarItemSpace)
                            make?.right.equalTo()(self.leftView.mas_right)?.offset()(-20)
                        })
                    } else {
                        item?.mas_makeConstraints({ make in
                            make?.top.equalTo()(0)
                            make?.bottom.equalTo()(0)
                            make?.left.equalTo()(20)
                        })
                    }
                }
                lastItem = item
            }
        }
    }
    
    private func _updateRightView() {
        // 刷新前移除视图
        for item in self.rightView.subviews {
            item.removeFromSuperview()
        }
        if (self.rightView.superview != nil) {
            self.rightView.removeFromSuperview()
        }
        
        if let itemIdentifiers = self.delegate?.toolbarRightDefaultItemIdentifiers?(self) {
            if (self.rightView.superview == nil) {
                self.addSubview(self.rightView)
                
                self.rightView.mas_makeConstraints { make in
                    make?.right.equalTo()(self.mas_right)?.offset()(0)
                    make?.top.equalTo()(self.mas_top)?.offset()(0)
                    make?.bottom.equalTo()(self.mas_bottom)?.offset()(0)
                }
            }
            
            var lastItem: KMToolbarItemView?
            for i in 0 ..< itemIdentifiers.count {
                let itemIdentifier = itemIdentifiers[i]
                
                var item: KMToolbarItemView?
                if itemIdentifier == KMToolbarDividerItemIdentifier {
                    item = KMToolbarItemView(itemIdentifier: itemIdentifier, postition: .imageOnly, withPopMenu: nil)
                } else if itemIdentifier == KMNewToolbarSpaceItemIdentifier {
                    item = KMToolbarItemView(itemIdentifier: itemIdentifier, postition: .imageOnly, withPopMenu: nil)
                    item?.layer?.backgroundColor = .clear
                    item?.imageViewBox.borderColor = .clear
                    item?.layer?.cornerRadius = 0.0;
                } else if let data = self.delegate?.toolbar?(self, itemFor: itemIdentifier) {
                    item = data
                }
                
                if (item == nil) {
                    continue
                }
                
                self.rightView.addSubview(item!)
                if (lastItem != nil) {
                    if (i == itemIdentifiers.count - 1) {
                        item?.mas_makeConstraints({ make in
                            make?.top.equalTo()(0)
                            make?.bottom.equalTo()(0)
                            make?.left.equalTo()(lastItem!.mas_right)?.offset()(KMToolbarItemSpace)
                            make?.right.equalTo()(self.rightView.mas_right)?.offset()(-20)
                        })
                    } else {
                        item?.mas_makeConstraints({ make in
                            make?.top.equalTo()(0)
                            make?.bottom.equalTo()(0)
                            make?.left.equalTo()(lastItem!.mas_right)?.offset()(KMToolbarItemSpace)
                        })
                    }
                } else {
                    if (i == itemIdentifiers.count - 1) {
                        item?.mas_makeConstraints({ make in
                            make?.top.equalTo()(0)
                            make?.bottom.equalTo()(0)
                            make?.left.equalTo()(self.rightView.mas_left)?.offset()(KMToolbarItemSpace)
                            make?.right.equalTo()(self.rightView.mas_right)?.offset()(-20)
                        })
                    } else {
                        item?.mas_makeConstraints({ make in
                            make?.top.equalTo()(0)
                            make?.bottom.equalTo()(0)
                            make?.left.equalTo()(0)
                        })
                    }
                }
                lastItem = item
            }
        }
    }
    
    override func updateLayer() {
        super.updateLayer()
        
        self.layer?.backgroundColor = .clear
    }
    
    // MARK: - View Methods
    
    override func viewWillMove(toWindow newWindow: NSWindow?) {
        super.viewWillMove(toWindow: newWindow)
        
        if (newWindow != nil && self._contentView == nil) {
            let leftitemIdentifiers = self.delegate?.toolbarLeftDefaultItemIdentifiers?(self) ?? []
            if (leftitemIdentifiers.count > 0) {
                self._updateMainView()
            }else {
                self._updateView()
            }

            self.resizeSubviews(withOldSize: self.frame.size)
    
//            NotificationCenter.default.addObserver(self, selector: #selector(toolbarCustomChangeNotification), name: KMToolbarCustomChangeNotification, object: nil)
            let topLine = NSBox(frame: CGRectMake(0, 0, self.frame.size.width, 0.5))
            topLine.boxType = .separator
            topLine.fillColor = .black
            self.addSubview(topLine)
            topLine.mas_makeConstraints { make in
                make?.left.right().equalTo()(self)
                make?.bottom.equalTo()(self.mas_bottom)?.offset()(-0.5)
                make?.height.offset()(0.5)
            }

//            NSBox *bottomLine = [[NSBox alloc] initWithFrame:];
            let bottomLine = NSBox(frame: CGRectMake(0, 0, self.frame.size.width, 0.5))
            bottomLine.boxType = .separator
            bottomLine.fillColor = .black
            self.addSubview(bottomLine)
            bottomLine.mas_makeConstraints { make in
                make?.left.right().equalTo()(self)
                make?.top.equalTo()(self.mas_top)?.offset()(0.1)
                make?.height.offset()(0.5)
            }
        };

        if (newWindow != nil) {
            self._addTrackingArea()
        }
    }
    
    override func resizeSubviews(withOldSize oldSize: NSSize) {
        super.resizeSubviews(withOldSize: oldSize)
        
        if (self._contentView == nil) {
            return;
        }
        let moreButtonWidth = 30.0
        let leftButtonWidth = 10.0
        var frame = self.contentView.frame

        var count = self.items.count
        var idx = count-1
        for item in self.items.reversed() {
            if (CGRectGetMaxX(item.frame) <= self.frame.size.width-moreButtonWidth-leftButtonWidth) {
                count = idx
                break
            }
            idx -= 1
        }
        if (count >= self.items.count) {
            return
        }
        frame.size.width = CGRectGetMaxX(self.items[count].frame)
        if (count == self.items.count-1) {
            frame.origin.x = (self.frame.size.width-frame.size.width)/2.0;
            self.moreButton.isHidden = true
            self._visibleItems = self.items
            self._invisibleItems = []
            self.contentView.mas_remakeConstraints { make in
                make?.centerX.equalTo()(0)
                make?.centerY.equalTo()(0)
            }
        } else {
            frame.origin.x = leftButtonWidth
            self.moreButton.mas_makeConstraints { make in
                make?.top.bottom().equalTo()(0)
                make?.width.offset()(moreButtonWidth)
                make?.right.equalTo()(self.mas_right)?.offset()(0)
            }
            self.moreButton.isHidden = false
            self._visibleItems.removeAll()
            for i in 0 ... count+1 {
                self._visibleItems.append(self.items[i])
            }
    //        self.invisibleItems = [self.items subarrayWithRange:NSMakeRange(count+1, self.items.count-count-1)];
            self.contentView.mas_remakeConstraints { make in
                make?.left.equalTo()(self.mas_left)?.offset()(10)
                make?.centerY.equalTo()(0)
            }
        }
        
        self._invisibleItems.removeAll()
        for item in self.items.reversed() {
            if (CGRectGetMaxX(item.frame) <= self.frame.size.width-moreButtonWidth-leftButtonWidth) {
                item.isHidden = false
            } else {
                item.isHidden = true
                self._invisibleItems.append(item)
            }
        }
    }
    
    func reloadData() {
        let leftitemIdentifiers = self.delegate?.toolbarLeftDefaultItemIdentifiers?(self) ?? []
        if (leftitemIdentifiers.count > 0) {
            self._updateMainView()
        } else {
            self._updateView()
        }
        
        self.resizeSubviews(withOldSize: self.frame.size)
    }
    
    func itemForItemIdentifier(_ itemIdentifier: String) -> KMToolbarItemView? {
        for item in self.items {
            if (item.itemIdentifier == itemIdentifier) {
                return item
            }
        }
        return nil
    }
    
    @objc func toolbarCustomChangeNotification() {
        self.reloadData()
    }
}