//
//  KMToolbarConfigViewController.swift
//  PDF Reader Pro
//
//  Created by tangchao on 2024/5/23.
//

import Cocoa

typealias KMToolbarConfigViewControllerCallback = (NSApplication.ModalResponse) -> Void
class KMToolbarConfigViewController: NSViewController {
    
    @IBOutlet weak var showLabel: NSTextField!
    @IBOutlet weak var collectionView: NSCollectionView!
    @IBOutlet weak var removedLabel: NSTextField!
    @IBOutlet weak var removedCollectionView: NSCollectionView!
    @IBOutlet weak var tipLabel: NSTextField!
    @IBOutlet weak var cancelButton: NSButton!
    @IBOutlet weak var confirmButton: NSButton!
    
    private let cellIdentifier_ = NSUserInterfaceItemIdentifier(rawValue: "ToolbarConfigCellIdentifier")
    
    var model = KMToolbarConfigModel()
    
    var callback: KMToolbarConfigViewControllerCallback?
    
    deinit {
        Swift.debugPrint("KMToolbarConfigViewController deinit.")
    }
    
    convenience init() {
        self.init(nibName: "KMToolbarConfigViewController", bundle: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.initDefalutValue()
    }
    
    func initDefalutValue() {
        self.showLabel.stringValue = NSLocalizedString("Show", comment: "")
        self.collectionView.delegate = self
        self.collectionView.dataSource = self
        
        self.collectionView.register(KMToolbarConfigViewItem.self, forItemWithIdentifier: self.cellIdentifier_)
        (self.collectionView.collectionViewLayout as? NSCollectionViewFlowLayout)?.scrollDirection = .horizontal
        self.collectionView.registerForDraggedTypes([NSPasteboard.PasteboardType.string])
        
        self.collectionView.allowsMultipleSelection = false
        self.collectionView.enclosingScrollView?.backgroundColor = .gridColor
        
        self.removedLabel.stringValue = NSLocalizedString("Hide", comment: "")
        self.removedCollectionView.delegate = self
        self.removedCollectionView.dataSource = self
        
        self.removedCollectionView.register(KMToolbarConfigViewItem.self, forItemWithIdentifier: self.cellIdentifier_)
        (self.removedCollectionView.collectionViewLayout as? NSCollectionViewFlowLayout)?.scrollDirection = .horizontal
        
        self.removedCollectionView.registerForDraggedTypes([NSPasteboard.PasteboardType.string])
        self.removedCollectionView.isSelectable = true
        
        self.tipLabel.stringValue = NSLocalizedString("Drag and drop to add, remove and reorder the tools.", comment: "")
        
        self.cancelButton.title = NSLocalizedString("Cancel", comment: "")
        self.cancelButton.target = self
        self.cancelButton.action = #selector(buttonClick)
        self.confirmButton.title = NSLocalizedString("Confirm", comment: "")
        self.confirmButton.target = self
        self.confirmButton.action = #selector(buttonClick)
    }
    
    @objc func buttonClick(_ sender: NSButton) {
        var resp: NSApplication.ModalResponse = .cancel
        if self.confirmButton.isEqual(to: sender) {
            resp = .OK
        }
        
        guard let block = self.callback else {
            return
        }
        block(resp)
    }
}

extension KMToolbarConfigViewController: NSCollectionViewDelegate, NSCollectionViewDataSource, NSCollectionViewDelegateFlowLayout {
    func numberOfSections(in collectionView: NSCollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        if self.removedCollectionView.isEqual(to: collectionView) {
            return self.model.removedCellIdentifiers?.count ?? 0
        }
        
        if let cnt = self.model.allowedCellIdentifiers?.count {
            return cnt + 2
        }
        return 0
    }
    
    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
        if self.removedCollectionView.isEqual(to: collectionView) {
            let cell = collectionView.makeItem(withIdentifier: self.cellIdentifier_, for: indexPath) as! KMToolbarConfigViewItem
            let itemId = self.model.removedCellIdentifiers?[indexPath.item] ?? ""
            let item = KMToolbarConfigTBItemView(itemIdentifier: itemId)
            self.model.setupMainItem(item)
            cell.itemView = item
            return cell
        }
        
        let cell = collectionView.makeItem(withIdentifier: self.cellIdentifier_, for: indexPath) as! KMToolbarConfigViewItem
        if self.model.isFirstSegI(at: indexPath.item) {
            cell.itemView = nil
        } else if self.model.isSecondSegI(at: indexPath.item) {
            cell.itemView = nil
        } else {
            var idx = indexPath.item
            if self.model.isRight(at: idx) {
                idx = idx - 2
            } else if self.model.isCenter(at: idx) {
                idx = idx - 1
            }
            
            let itemId = self.model.allowedCellIdentifiers?[idx] ?? ""
            let item = KMToolbarConfigTBItemView(itemIdentifier: itemId)
            self.model.setupMainItem(item)
            cell.itemView = item
        }
        
        return cell
    }
    
    // Layout
    
    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
        if self.removedCollectionView.isEqual(to: collectionView) {
            let itemId = self.model.removedCellIdentifiers?[indexPath.item] ?? ""
            let item = KMToolbarItemView(itemIdentifier: itemId)
            self.model.setupMainItem(item)
            return NSSize(width: item.itemWidth, height: 48)
        }
        
        if self.model.isFirstSegI(at: indexPath.item) {
            return NSSize(width: self.model.segItemWidth, height: 48)
        } else if self.model.isSecondSegI(at: indexPath.item) {
            return NSSize(width: self.model.segItemWidth, height: 48)
        }
        
        var idx = indexPath.item
        if self.model.isRight(at: idx) {
            idx = idx - 2
        } else if self.model.isCenter(at: idx) {
            idx = idx - 1
        }
        let itemId = self.model.allowedCellIdentifiers?[idx] ?? ""
        let item = KMToolbarItemView(itemIdentifier: itemId)
        self.model.setupMainItem(item)
        return NSSize(width: item.itemWidth, height: 48)
    }
    
    // 纵向间距
    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 5
    }
    
    // 横向间距
    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        if self.removedCollectionView.isEqual(to: collectionView) {
            return 12
        }
        return 5
    }
    
    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, insetForSectionAt section: Int) -> NSEdgeInsets {
        return .init(top: 6, left: 10, bottom: 6, right: 10)
    }
    
    func collectionView(_ collectionView: NSCollectionView, shouldSelectItemsAt indexPaths: Set<IndexPath>) -> Set<IndexPath> {
        return indexPaths
    }
    
    // Drag & Drop
    
    func collectionView(_ collectionView: NSCollectionView, canDragItemsAt indexPaths: Set<IndexPath>, with event: NSEvent) -> Bool {
        if self.removedCollectionView.isEqual(to: collectionView) {
            return true
        }
        guard let ip = indexPaths.first else {
            return false
        }
        if self.model.isSeg(at: ip.item) {
            return false
        }
        return true
    }
    
    func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {
        return String(indexPath.item) as NSPasteboardWriting
    }
    
    func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {
        let draggingSource = draggingInfo.draggingSource as? NSCollectionView
        if collectionView.isEqual(self.removedCollectionView) {
            if self.collectionView.isEqual(to: draggingSource) {
                return .copy
            } else {
                return .move
            }
        }
        
        if collectionView.isEqual(self.collectionView) {
            if self.removedCollectionView.isEqual(to: draggingSource) {
                return .copy
            } else {
                return .move
            }
        }
        return []
    }
    
    func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool {
        guard let draggingSource = draggingInfo.draggingSource as? NSCollectionView else {
            return false
        }
        
        if collectionView.isEqual(self.removedCollectionView) {
            let isIn = self.removedCollectionView.isEqual(to: draggingSource)
            if isIn { // 暂不支持内部拖拽排序
                return false
            }
                
            // 外部拖拽
            if let data = draggingInfo.draggingPasteboard.pasteboardItems?.first?.string(forType: .string) {
                if let itemIdx = Int(data) {
                    if self.model.removeItem(at: itemIdx) {
                        self.collectionView.reloadData()
                        self.removedCollectionView.reloadData()
                        return true
                    }
                }
            }
            return false
        }
        
        // 显示区域
        let isIn = self.collectionView.isEqual(to: draggingSource)
        if isIn { // 内部拖拽
            if let data = draggingInfo.draggingPasteboard.pasteboardItems?.first?.string(forType: .string) {
                if let itemIdx = Int(data) {
                    if itemIdx == indexPath.item { // 无效拖拽
                        return false
                    }
                    if self.model.moveItem(itemIdx: itemIdx, to: indexPath.item) {
                        self.collectionView.reloadData()
                        return true
                    }
                }
            }
            return false
        }
        
        // 外部拖拽
        if let data = draggingInfo.draggingPasteboard.pasteboardItems?.first?.string(forType: .string) {
            if let itemIdx = Int(data) {
                if let itemId = self.model.removedCellIdentifiers?.safe_element(for: itemIdx) as? String {
                    if self.model.addItem(itemId: itemId, at: indexPath.item) {
                        self.collectionView.reloadData()
                        self.removedCollectionView.reloadData()
                        return true
                    }
                }
            }
        }
        return false
    }

    
}