//
//  Helper.swift
//  AlDente
//
//  Created by David Wernhart on 14.02.20.
//  Copyright © 2020 David Wernhart. All rights reserved.
//

import Cocoa
import SwiftUI
import ServiceManagement
import Foundation

protocol HelperDelegate {
    func OnMaxBatRead(value: UInt8)
}

class Helper{
    
    static let instance = Helper()
    
    public var delegate: HelperDelegate?
    
//    var receiveMessage = "" {
//            didSet {
//                DispatchQueue.main.async {
//                    print(self.receiveMessage)
//    //                if self.receiveMessage.isEmpty {
//    //                    self.clearButton.isEnabled = false
//    //                } else {
//    //                    self.clearButton.isEnabled = true
//    //                }
//                }
//            }
//        }
        
    lazy var helperToolConnection: NSXPCConnection = {
        let connection = NSXPCConnection(machServiceName: "com.davidwernhart.Helper.mach", options: .privileged)
        connection.remoteObjectInterface = NSXPCInterface(with: HelperToolProtocol.self)
           
        connection.resume()
        return connection
    }()
    
    @objc func installHelper() {
        print("trying to install helper!")
        var status: OSStatus = noErr
        let helperID = "com.davidwernhart.Helper" as CFString//Prefs.helperID as CFString

        var authItem = AuthorizationItem(name: kSMRightBlessPrivilegedHelper, valueLength: 0, value: nil, flags: 0)
        var authRights = AuthorizationRights(count: 1, items: &authItem)
        let authFlags: AuthorizationFlags = [.interactionAllowed, .preAuthorize, .extendRights]
        var authRef: AuthorizationRef? = nil
        status = AuthorizationCreate(&authRights, nil, authFlags, &authRef)
        if status != errAuthorizationSuccess {
            print(SecCopyErrorMessageString(status,nil))
            print("Error:", String(status))
        }
        var error: Unmanaged<CFError>? = nil
        SMJobBless(kSMDomainSystemLaunchd, helperID, authRef, &error)
        if let e = error?.takeRetainedValue() {
            print("Domain:", CFErrorGetDomain(e))
            print("Code:", CFErrorGetCode(e))
            print("UserInfo:", CFErrorCopyUserInfo(e))
            print("Description:", CFErrorCopyDescription(e))
            print("Reason:", CFErrorCopyFailureReason(e))
            print("Suggestion:", CFErrorCopyRecoverySuggestion(e))
        }
    }


    @objc func writeMaxBatteryCharge(setVal: UInt8){
        SMCWriteByte(key: "BCLM", value: setVal)
        

    }
    
    @objc func readMaxBatteryCharge(){
        SMCReadByte(key:"BCLM",withReply: { (value) in
            print(String(value))
            self.delegate?.OnMaxBatRead(value: value)
        })
    }

    @objc func checkHelperVersion() {
        print("checking helper version")
        if let helper = helperToolConnection.remoteObjectProxyWithErrorHandler({ (error) in
            let e = error as NSError
            print("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
            self.installHelper()
            //self.receiveMessage.append("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
        }) as? HelperToolProtocol {            
            helper.getVersion(withReply: { (version) in
                print("helperVersion:", helperVersion, " version from helper:",version)
                if(!helperVersion.elementsEqual(version)){
                    self.installHelper()
                }
                //self.receiveMessage.append("Version: \(version)\n")
            })
        }
    }

    @objc func SMCReadByte(key:String, withReply reply: @escaping (UInt8) -> Void){
        if let helper = helperToolConnection.remoteObjectProxyWithErrorHandler({ (error) in
            let e = error as NSError
            print("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
            //self.receiveMessage.append("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
        }) as? HelperToolProtocol {
            helper.readSMCByte(key: key) { (value) in
                reply (value)
            }
        }
    }

    @objc func SMCWriteByte(key:String,value:UInt8){
        if let helper = helperToolConnection.remoteObjectProxyWithErrorHandler({ (error) in
            let e = error as NSError
            print("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
            //self.receiveMessage.append("Remote proxy error \(e.code): \(e.localizedDescription) \(e.localizedRecoverySuggestion ?? "---")")
        }) as? HelperToolProtocol {
            helper.setSMCByte(key: key,value: value)
        }
    }
}
