//
//  ViewController.swift
//  KdanAuto
//
//  Created by 朱东勇 on 2022/11/17.
//

import Cocoa

class ViewController : NSViewController, SettingViewControllerDelegate, AutoTestAdvanceSettingViewDelegate, TestCaseCellViewDelegate,
                       NSTableViewDelegate, NSTableViewDataSource {
    
    @IBOutlet var customView : NSView!
    
    @IBOutlet var settingVCWindow : NSWindow!
    @IBOutlet var settingVC : SettingViewController!
    
    @IBOutlet var itemsList : NSTableView!
    var _currentCellInfo : AutoTestCellInfo?
    @IBOutlet var advanceView : AutoTestAdvanceSettingView!
    
    @IBOutlet var startBtn : NSButton!
    @IBOutlet var replaceAllBtn : NSButton!
    var _isProcessing : Bool!
    
    var _selectFileType : String! = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        customView.wantsLayer = true;
        customView.layer?.borderColor = NSColor.lightGray.withAlphaComponent(0.4).cgColor
        customView.layer?.borderWidth = 1
        
        advanceView.wantsLayer = true
        advanceView.layer?.borderColor = NSColor.lightGray.withAlphaComponent(0.4).cgColor
        advanceView.layer?.borderWidth = 1
        
        // Load Infos
        let path = Bundle.main.path(forResource: "AutoTestProperty", ofType: "plist")!
        let url = URL.init(fileURLWithPath: path, isDirectory: false)
        let initInfo = try! NSDictionary.init(contentsOf: url, error: ()) 
        
        testFileTypes = initInfo.allKeys as [String]
        testTypeInfo = initInfo as NSDictionary
                
        //
        advanceView.delegate = self;
        updateProcessStatus()
        
        self.replaceAllBtn.isEnabled = false;
        
        DispatchQueue.global().async {
            for fileType in testFileTypes {
                let types = testTypeInfo[fileType] as! NSArray
                for typeInfo in types {
                    let ti = typeInfo as! NSDictionary
                    let type = ti["Type"] as! NSString
                    
                    let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
                    
                    if testObject != nil &&
                        testObject!.canUpdateRefImage() {
                        DispatchQueue.main.sync {
                            self.replaceAllBtn.isEnabled = true;
                        }
                        break
                    }
                }
            }
        }
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
    
    func reloadListData() {
        itemsList.reloadData()
    }

    // Update
    func updateProcessStatus() {
        startBtn.wantsLayer = true;
        startBtn.layer?.cornerRadius = startBtn.frame.width / 2.0
        startBtn.layer?.backgroundColor = NSColor.init(red: 0, green: 0.6, blue: 0.6, alpha: 1).cgColor;
        startBtn.contentTintColor = NSColor.white
        
    }
    
    // Setter & Getter
    func setCurrentCellInfo(_ cellInfo : AutoTestCellInfo?) {
        _currentCellInfo = cellInfo
        
        if (nil != _currentCellInfo) {
            let autoTestObj = AutoTest.autoTestFor(NSString(string: (_currentCellInfo?.fileType())!), type:NSString(string: (_currentCellInfo?.typeInfo()["Type"] as! String)))
            
            advanceView.setAutoTestObj(autoTestObj)
        }else {
            advanceView.setAutoTestObj(nil)
        }
    }
    
    
    // IBAction
    @IBAction func showSettingVC(_ sender:NSButton) {
        let settingVC = SettingViewController.shared()
        settingVC.delegate = self
        settingVC.show()
    }

    @IBAction func startAction(_ sender:NSButton) {
        let path = DataModel.shared.directoryPath();
        
        if NSString(string: path).isEqual(to: "") || !FileManager.default.fileExists(atPath: path) {
            return
        }
        
        _isProcessing = true;
        updateProcessStatus()
        
        startBtn.isEnabled = false
        startBtn.title = "Doing"
        
        DispatchQueue.global().async {
            var report = NSMutableAttributedString.init()
            DataModel.shared.generaNewReportID()
            
            let testSemaphore = DispatchSemaphore(value: 0)
            
            // Update For Waiting
            for fileType in testFileTypes {
                let types = testTypeInfo[fileType] as! NSArray
                for typeInfo in types {
                    let ti = typeInfo as! NSDictionary
                    let type = ti["Type"] as! NSString
                    
                    let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
                    testObject?.setStatus(.Wait)
                }
                DispatchQueue.main.sync {
                    self.reloadListData()
                }
            }
            
            for fileType in testFileTypes {
                let types = testTypeInfo[fileType] as! NSArray
                for typeInfo in types {
                    let ti = typeInfo as! NSDictionary
                    let type = ti["Type"] as! NSString
                    
                    let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
                    testObject?.setStatus(.Process)
                    DispatchQueue.main.sync {
                        self.reloadListData()
                    }
                    if nil != testObject {
                        let queue = DispatchQueue.global()
                        queue.async {
                            testObject?.autoTest()
                            
                            testSemaphore.signal()
                        }
                        testSemaphore.wait()
                        
                        if let cReport = testObject?.testReport() {
                            report.append(cReport)
                        }
                    }
                    testObject?.setStatus(.Finished)
                    DispatchQueue.main.sync {
                        self.reloadListData()
                    }
                }
                
//                for typeInfo in types {
//                    let ti = typeInfo as! NSDictionary
//                    let type = ti["Type"] as! NSString
//                    
//                    let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
//                    testObject?.setStatus(.Normal)
//                }
            }

            do {
                let rtfData = try report.data(from: .init(location: 0, length: report.length),
                                                 documentAttributes: [.documentType: NSAttributedString.DocumentType.rtf])

                let path = DataModel.shared.directoryPath().appendingFormat("/TestReport_\(DataModel.shared.latestReportID()!).rtf")
                try rtfData.write(to: NSURL.fileURL(withPath: path))
            } catch {
                print(error)
            }
            
            DispatchQueue.main.async {
                self._isProcessing = false
                self.updateProcessStatus()
                self.startBtn.isEnabled = true
                self.startBtn.title = "Start"
                
                self.replaceAllBtn.isEnabled = true
            }
        }
    }
    
    @IBAction func relpaceAllAction(_ sender:NSButton) {
        // Replace all refrence images for all type
        self.startBtn.isEnabled = false
        self.replaceAllBtn.isEnabled = false
        
        DispatchQueue.global().async {
            // Update For Waiting
            for fileType in testFileTypes {
                let types = testTypeInfo[fileType] as! NSArray
                for typeInfo in types {
                    let ti = typeInfo as! NSDictionary
                    let type = ti["Type"] as! NSString
                    
                    let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
                    testObject?.updateRefImage()
                }
                DispatchQueue.main.sync {
                    self.reloadListData()
                }
            }
            
            DispatchQueue.main.async {
                self.startBtn.isEnabled = true
            }
        }
    }
    
    @IBAction func selectAllTestItem(_ sender:NSButton) {
        for fileType in testFileTypes {
            let types = testTypeInfo[fileType] as! NSArray
            for typeInfo in types {
                let ti = typeInfo as! NSDictionary
                let type = ti["Type"] as! NSString
                
                let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
                if nil != testObject {
                    testObject?.setSelectedKeys((testObject?.keys())!)
                }
            }
            self.reloadListData()
            
            advanceView.setAutoTestObj(advanceView._autoTestObj)
        }
    }
    
    @IBAction func diselectAllTestItem(_ sender:NSButton) {
        for fileType in testFileTypes {
            let types = testTypeInfo[fileType] as! NSArray
            for typeInfo in types {
                let ti = typeInfo as! NSDictionary
                let type = ti["Type"] as! NSString
                
                let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
                if nil != testObject {
                    testObject?.setSelectedKeys([])
                }
            }
            self.reloadListData()
            
            advanceView.setAutoTestObj(advanceView._autoTestObj)
        }
    }
    
    // TableView Delegate
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        let cellInfo = AutoTestCellInfo.initWithRow(row)
        
        if cellInfo.isFileType() {
            let cellView = TestFileTypeCellView.shared()
            
            let title = cellInfo.fileType()
            
            cellView?.setTitle(title)
            
            return cellView
        }else {
            let cellView = TestCaseCellView.shared()
            
            let autoTestObj = AutoTest.autoTestFor(NSString(string: (cellInfo.fileType())), type:NSString(string: (cellInfo.typeInfo()["Type"] as! String)))
            
            cellView?.setAutoTestObj(autoTestObj);
            cellView?.delegate = self;
            
            return cellView
        }
    }
    
    func selectionShouldChange(in tableView: NSTableView) -> Bool {
        
        
        return true
    }
    
    func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
        
        return true
    }
    
    func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
        
        return false
    }
    
    func tableView(_ tableView: NSTableView, mouseDownInHeaderOf tableColumn: NSTableColumn) {
        
    }
    
    func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn) {
        
    }
    
    func tableView(_ tableView: NSTableView, didDrag tableColumn: NSTableColumn) {
        
    }
    
    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
        let cellInfo = AutoTestCellInfo.initWithRow(row)
        
        if cellInfo.isFileType() {
            return 30
        }else {
            return 60
        }
    }
    
    func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
        return false
    }
    
    func tableView(_ tableView: NSTableView, sizeToFitWidthOfColumn column: Int) -> CGFloat {
        return tableView.frame.width
    }
    
    func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
        return []
    }
    
    func tableViewSelectionDidChange(_ notification: Notification) {
        if ((notification.object as! NSTableView) == itemsList) {
            let selectRow = itemsList.selectedRow
            
            if selectRow != -1 {
                let cellInfo = AutoTestCellInfo.initWithRow(selectRow)
                
                if cellInfo.isFileType() {
                    let isExpend = DataModel.shared.isExpand(cellInfo.fileType())
                    
                    DataModel.shared.setIsExpand(cellInfo.fileType(), expand: (!isExpend))
                    itemsList.reloadData()
                }else {
                    self.setCurrentCellInfo(cellInfo)
                }
            }else {
                
            }
        }
        
    }
    
    
    
    // TableView Data Source
    func numberOfRows(in tableView: NSTableView) -> Int {
        var count = testFileTypes.count
        
        for fileType in testFileTypes {
            //当前文件类型是否为展开
            if (DataModel.shared.isExpand(fileType)) {
                let testTypes = testTypeInfo[fileType] as! NSArray
                
                count = count + testTypes.count
            }
        }
        
        return count
    }
    
    /* This method is required for the "Cell Based" TableView, and is optional for the "View Based" TableView. If implemented in the latter case, the value will be set to the view at a given row/column if the view responds to -setObjectValue: (such as NSControl and NSTableCellView). Note that NSTableCellView does not actually display the objectValue, and its value is to be used for bindings. See NSTableCellView.h for more information.
     */
//    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
//        return testCaseNames[row]
//    }
    
    
    // SettingViewConntroller Handle
    func settingViewDidFinished() {
        reloadListData()
    }
    
    //AutoTestAdvanceSettingView Delegate
    func advanceSettingDidUpdate(_ settingView: NSView?) {
        if (nil != _currentCellInfo) {
            itemsList.reloadData(forRowIndexes: IndexSet(integer: IndexSet.Element((_currentCellInfo?._row)!)),
                                 columnIndexes: IndexSet(integer: IndexSet.Element(0)))
        }else {
            reloadListData()
        }
    }
    
    //TestCaseCellViewDelegate
    func selectKeyDidUpdate(_ cell: NSTableCellView?) {
        advanceView._autoTestObj = advanceView._autoTestObj
    }
    
}

