//
//  XPMobileSDK.swift
//  XProtect
//
//  Created by Ivelin Tsankov on 1/25/17.
//  Copyright © 2017 Milestone Systems A/S. All rights reserved.
//

import Foundation

open class XPMobileSDK: NSObject {
    open static var serverFeatures: NSDictionary? {
        return XPSDKConnection.sharedConnection.features
    }
    
    //MARK: Connect method
    /**
     Connect method
     
     - Parameters:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func connect(successHandler: SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.connect(successHandler: successHandler, failureHandler: failureHandler)
    }
    
    open class func disconnect() -> XPSDKRequest {
        return self.disconnect(withSuccessHandler: nil, failureHandler: nil)
    }
    
    open class func disconnect(withSuccessHandler successHandler: SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest  {
        return XPSDKConnection.sharedConnection.disconnect(withSuccessHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Connect with url method
     
     - Parameters:
        - urlString: The URL String to which will connect
        - successHandler: The success block which returns XPSDKResponse
        - failureHandler: The failure block which returns NSError
     */
    open class func connectWithURLString(_ urlString: String, successHandler: SuccessResponse?, failureHandler: FailureBlock?)   {
        XPSDKConnection.sharedConnection.setupWithURLString(urlString)
        self.connect(successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Connect with url method
     
     - Parameters:
     - urlString: The URL String to which will connect
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func connectWithServerInfo(_ serverInfo: XPSDKServerInfo, successHandler: SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.setupWithServerInfo(serverInfo)        
        self.connect(successHandler: successHandler, failureHandler: failureHandler)
    }
    
    //MARK: Login method
    /**
     Login method
     
     - Parameters:
        - username: The username
        - password: The password
        - successHandler: The success block which returns XPSDKResponse
        - failureHandler: The failure block which returns NSError
     */
    open class func loginForUsername(_ username: String, password: String, shouldSave: Bool, successHandler: SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest {
        XPSDKConnection.sharedConnection.setupWithUsername(username, password: password, shouldSave: shouldSave)

        return XPSDKConnection.sharedConnection.login(withSuccessHandler: successHandler, failureHandler: failureHandler)!
    }
    
    //MARK: Connect And Login method
    /**
     Login method
     
     - Parameters:
     - urlString: The URL String to which will connect
     - username: The username
     - password: The password
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func connectAndLoginForURLString(_ urlString: String, username: String, password: String, shouldSave: Bool, successHandler: SuccessResponse?, failureHandler: FailureBlock?) {
        self.connectWithURLString(urlString, successHandler: { (connectResponse) in
            self.loginForUsername(username, password: password, shouldSave: shouldSave, successHandler: successHandler, failureHandler: failureHandler)
            }, failureHandler: failureHandler)
    }
    
    //MARK: Connect And Login method
    /**
     Login method
     
     - Parameters:
     - urlString: The URL String to which will connect
     - username: The username
     - password: The password
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func connectAndLoginForServerInfo(_ serverInfo: XPSDKServerInfo, username: String, password: String, shouldSave: Bool, successHandler: SuccessResponse?, failureHandler: FailureBlock?) {
        self.connectWithServerInfo(serverInfo, successHandler: { (connectResponse) in
            self.loginForUsername(username, password: password, shouldSave: shouldSave, successHandler: successHandler, failureHandler: failureHandler)
        }, failureHandler: failureHandler)
    }
    
    
    open class func requestSecondStepAuthenticationPin(withSuccessHandler successHandler: SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest  {
       return XPSDKConnection.sharedConnection.requestSecondStepAuthenticationPin(withSuccessHandler: successHandler, failureHandler: failureHandler)
    }
    
    open class func verifySecondStepAuthenticationPin(withPin pin: String, successHandler: SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest  {
        return XPSDKConnection.sharedConnection.verifySecondStepAuthenticationPin(withPin: pin, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    //MARK: Request stream

    /**
     Request stream method
     
     - Parameters:
     - cameraID: the ID of camera for which the video stream is requested
     - size: The size of the video to be streamed
     - signal: The connection signal (live, playback or upload)
     - fps: Frames per second
     - userInitiatedDownsampling:
     - keyFramesOnly:
     - resizeSupported:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func requestStream(forCameraID cameraID: XPSDKViewID,
                              size: CGSize,
                              method: XPSDKVideoConnectionMethod,
                              signal: XPSDKVideoConnectionSignal,
                              fps:Int, compressionLevel:Int,
                              userInitiatedDownsampling:Bool,
                              keyFramesOnly:Bool,
                              resizeSupported: Bool,
                              time: NSDate?,
                              usesTranscoding: Bool,
                              successHandler: @escaping (XPSDKResponse, XPSDKVideoConnection) -> Void,
                              failureHandler: FailureBlock?) {
        
        XPSDKConnection.sharedConnection.requestStream(forCameraID: cameraID, size: size, method: method, signal: signal, fps: fps, compressionLevel: compressionLevel, userInitiatedDownsampling: userInitiatedDownsampling, keyFramesOnly: keyFramesOnly, resizeSupported: resizeSupported, time: time, usesTranscoding: usesTranscoding, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Cancel request stream method
     
     - Parameters:
     - request: The request that will be cancelled
     */
    open class func cancelRequestStream(request : XPSDKRequest) {
        XPSDKConnection.sharedConnection.cancelRequestStream(request: request)
    }
    
    //MARK: Change stream
    /**
     Cancel request stream method
     
     - Parameters:
     - request: The request that will be cancelled
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func changeStream(forVideoID videoID: String, fps: Int, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.changeStream(forVideoID: videoID, fps: fps, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - size:
     - sourceRect
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func changeStream(forVideoID videoID: String, size: CGSize, sourceRect: CGRect, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.changeStream(forVideoID: videoID, size: size, sourceRect: sourceRect, successHandler: successHandler, failureHandler: failureHandler)
    }

    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - playSpeed:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func changeStream(forVideoID videoID: String, playSpeed: Float, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.changeStream(forVideoID: videoID, playSpeed: playSpeed, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func previousSequence(forVideoID videoID: String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.previousSequence(forVideoID: videoID, successHandler: successHandler, failureHandler: failureHandler)
    }

    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func nextSequence(forVideoID videoID: String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.nextSequence(forVideoID: videoID, successHandler: successHandler, failureHandler: failureHandler)
    }

    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func previousFrame(forVideoID videoID: String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.previousFrame(forVideoID: videoID, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func nextFrame(forVideoID videoID: String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.nextFrame(forVideoID: videoID, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - timestamp:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func seekToTimestamp(forVideoID videoID: String, timestamp:NSNumber, seekType: String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.seekToTimestamp(forVideoID: videoID, timestamp: timestamp, seekType: seekType, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - time:
     - seekType:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func seekToTime(forVideoID videoID: String, time: NSDate, seekType: String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.seekToTime(forVideoID: videoID, time: time, seekType: seekType, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Cancel request stream method
     
     - Parameters:
     - videoID:
     - ptzMotion:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func moveCamera(forVideoID videoID: String, ptzMotion: XPSDKPTZMotion, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
       XPSDKConnection.sharedConnection.moveCamera(forVideoID: videoID, ptzMotion: ptzMotion, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Move camera method with ptz preset
     
     - Parameters:
     - videoID:
     - ptzPreset:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func moveCamera(forVideoID videoID: String, ptzPreset:XPSDKCameraPTZPreset, successHandler:SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.moveCamera(forVideoID: videoID, ptzPreset: ptzPreset, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    //MARK: Close stream
    /**
     Close video connection
     
     - Parameters:
     - videoConnection: the video connection that will be closed
     - size: The username
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func closeVideoConnection(videoConnection: XPSDKVideoConnection, successHandler:SuccessResponse?, failureHandler: FailureBlock?){
         XPSDKConnection.sharedConnection.closeVideoConnection(videoConnection: videoConnection, successHandler: successHandler, failureHandler: failureHandler)
    }

    //MARK: Views
    /** Get all views and cameras method
 
    - Parameters:
    - successHandler: The success block which returns XPSDKResponse
    - failureHandler: The failure block which returns NSError
    */
    open class func getAllViewsAndCameras(withSuccessHandler successHandler: SuccessResponse?, failureHandler: FailureBlock?) {
        XPSDKConnection.sharedConnection.getAllViewsAndCameras(withSuccessHandler: successHandler, failureHandler: failureHandler)
    }
    
    /** Get subviews of view
     
     - Parameters:
     - viewId: ID of view which subviews will be returned
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func getSubviewsOfView(withId viewId:String, successHandler: SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest {
        return XPSDKConnection.sharedConnection.getSubviewsOfView(withId:viewId, successHandler:successHandler, failureHandler: failureHandler)
    }
    
    //MARK: Outputs & Events
    /** Get outputs and events method
     
     - Parameters:
     - cameraId: The camera ID for which the outputs and events will be returned
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func getOutputsAndEvents(forCameraId cameraId:String, successHandler: SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest {
        return XPSDKConnection.sharedConnection.getOutputsAndEvents(forCameraId: cameraId, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /** Activate output
     
     - Parameters:
     - objectId: The ID of Output/Event to be activated
     - triggerType: The type of trigger (Output or Event)
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func requestActivate(forObjectId objectId:String, triggerType:String, successHandler: SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest {
        return XPSDKConnection.sharedConnection.requestActivate(forObjectId:objectId, triggerType:triggerType, successHandler:successHandler, failureHandler: failureHandler)
    }

    //MARK: Alarms
    /** Get alarms method
     
     - Parameters:
     - count: number of the requested alarms
     - timestamp: timestamp
     - op: operator
     - myAlarms: flag for requesting only my alarms
     - excludedStates: states to be excluded
     - excludedPriorities: priorites to be excluded
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func getAlarms(withCount count:Int, timestamp:String, op:String, myAlarms:Bool, excludedStates:String, excludedPriorities:String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest {
        return XPSDKConnection.sharedConnection.getAlarms(withCount:count, timestamp:timestamp, op:op, myAlarms:myAlarms, excludedStates:excludedStates, excludedPriorities:excludedPriorities, successHandler:successHandler, failureHandler:failureHandler)
    }
    
    /** Get a single alarm
     
     - Parameters:
     - alarmId: the ID of the alarm which is requested
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func getAlarm(withId alarmId:String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest {
        return XPSDKConnection.sharedConnection.getAlarm(withId:alarmId, successHandler: successHandler, failureHandler: failureHandler)
    }
    
    /**
     Get alarm data settings method
     
     - Parameters:
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func getAlarmDataSettings(withSuccessHandler successHandler:SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest {
        return XPSDKConnection.sharedConnection.getAlarmDataSettings(withSuccessHandler: successHandler ,failureHandler: failureHandler)
    }
    
    /**
     Acknowledge Alarm method
     
     - Parameters:
     - alarmId: The ID of the alarm to be acknowledged
     - successHandler: The success block which returns XPSDKResponse
     - failureHandler: The failure block which returns NSError
     */
    open class func acknowledgeAlarm(withId alarmId: String, successHandler:SuccessResponse?, failureHandler: FailureBlock?) -> XPSDKRequest {
        return XPSDKConnection.sharedConnection.acknowledgeAlarm(withId: alarmId, successHandler: successHandler, failureHandler: failureHandler)
    }
        
    open class func setupLogger(showInDebug: Bool, showInRelease: Bool, showDate: Bool, showLevel: Bool, showBundleName: Bool, showFileName: Bool, showLineNubmer: Bool, showFunctionName: Bool, showLevels: [Level]?) {
        log.setup(showInDebug: showInDebug, showInRelease: showInRelease, showDate: showDate, showLevel: showLevel, showBundleName: showBundleName, showFileName: showFileName, showLineNubmer: showLineNubmer, showFunctionName: showFunctionName, showLevels: showLevels)
    }
    
    open class func setAuthenticationComplete(_ authenticationComplete: Bool) {
        XPSDKConnection.sharedConnection.authenticationComplete = authenticationComplete
    }
    
    //MARK: Delegates methods
    /**
     Add Delegate method
     
     - Parameters:
     - delegate: Add delegate to set of delegates
     */
    open class func addDelegate(_ delegate: XPMobileSDKConnectionDelegate) {
        XPSDKConnection.sharedConnection.addDelegate(delegate)
    }
    
    /**
     Remove Delegate method
     
     - Parameters:
     - delegate: Remove delegate from set of delegates
     */
    open class func removeDelegate(_ delegate: XPMobileSDKConnectionDelegate) {
        XPSDKConnection.sharedConnection.removeDelegate(delegate)
    }
    
    /**
     Stop All Sessions
     */
    open class func stopAllSessions() {
        XPSDKConnection.sharedConnection.stopAllSessions()
    }
    
}
