//
//  MobiControlConnectionManager.m
//  iOSAgent
//
//  Created by SOTI Inc. on 2015-06-11.
//  Copyright (c) 2015 SOTI Inc. All rights reserved.
//

#import "MobiControlConnectionManager.h"
// Import the file to get an access to public SDK API
#import "AgentSdk.h"

// The class implements AgentSdkCoreProtocol protocol to get notifications from the underlaying SDK about connection/enrollment state.
// Current example app is designed to demonstrate how to receive only connection (connectionStatusUpdate:errorMsg: handler) and enrollment (enrollmentStatusUpdate:enrollmentURL: handler) notifications.
@interface MobiControlConnectionManager () <AgentSdkCoreProtocol>

/*!
 Keeps strong reference to the SDK itself. App has to have such reference all the time it uses SDK API.
 */
@property (nonatomic, strong) AgentSdkCore *agentSdkCore;
@end


@implementation MobiControlConnectionManager

#pragma mark - LIFE CYCLE

+ (id)defaultMobiControlConnectionManager {

    // Just a standart logic to implement Singleton pattern 
    static dispatch_once_t pred = 0;
    __strong static id sharedObject = nil;
    
    dispatch_once(&pred, ^{
        sharedObject = [[self alloc] init];
    });
    
    return sharedObject;
}

- (id)init {
    self = [super init];

    // The SDK writes log messages to a console (standart output).
    // To make SDK initialization log messages visible it's required to make the API calls below. They temporarily duplicate stderr.
    // 1.
    int stderrSave = dup(STDERR_FILENO);

    if (self) {
        // Create SDK instance. AgentSdkCore is a singleton.
        self.agentSdkCore = [AgentSdkCore getInstance];
        // Register self to receive notifications from SDK
        [self.agentSdkCore registerDelegate:self];
        // Set app capability to All if the requires more than just Remote View capability
        // [self.agentSdkCore setAppCapability:kAPP_CAPABILITIES_ALL];
    }
 
    // 2. restore back stderr
    fflush(stderr);
    dup2(stderrSave, STDERR_FILENO);
    close(stderrSave);
    
    return self;
}



#pragma mark - GETTERS

- (BOOL)isEnrolled {
    // get enrollment state from the SDK
    return (kEnrollmentStateEnrolled == [self.agentSdkCore getEnrollmentState]);
}

- (BOOL)isConnected {
    // get connection state from the SDK
    return [self.agentSdkCore isConnected];
}

- (BOOL)isAppConfigAvailable {
    // to request SDK App Config
    return [self.agentSdkCore appConfigAvailable];
}


#pragma mark - AGENTSDK DELEGATE
/*! 
 A delegate callback for receiving connection state change notifications.
 @param status
    keeps connection state value
 @param error
    in a case of an error this variable stores error description
 */
- (void) connectionStatusUpdate:(ConnectionStatus)status errorMsg:(NSString *)error
{
    NSLog(@"connectionStatus = %@, error = %@", status, [error description]);
    
    if (kConnectionStatusOK == status)
    {
    }
    else if (kConnectionStatusDisconnected == status)
    {
    }
    else if( kConnectionStatusFailed == status)
    {
    }
   
    // Updating UI to reflect changes
    self.callbackUpdateStatus(nil);
    self.callbackUpdateUI([NSString stringWithUTF8String:__FUNCTION__]);
}

- (void) enrollmentStatusUpdate:(EnrollmentStatus)status enrollmentURL:(NSString*)url
{
    NSLog(@"enrollmentStatusUpdate = %@, enrollment url = %@", status, url);
    //
    // response from enrollment so lets enable enrollment controls again
    //
    if (kEnrollmentStatusEnrolled == status)
    {
        // Updating UI to reflect changes
        self.callbackUpdateStatus(nil);
        self.callbackUpdateUI([NSString stringWithUTF8String:__FUNCTION__]);
    }
   
  
}


#pragma mark - ACTIONS

// Perform Connect to MobiControl
- (void)connectToMobiControl {

    // Update UI
    self.callbackUpdateUI(@"connectToMobiControl");
    
    // Check if already connected to MobiControl
    if (self.isEnrolled) {
        // Update UI
        self.callbackUpdateStatus(@"Connecting connectToDS");
        
        // We are enrolled already Initiate connection
        [self.agentSdkCore connectToDS];
    } else {
        // Not enrolled yet
        // Update UI
        self.callbackUpdateStatus(@"Connecting connectToDSUsingAppConfig");

        // Connect operation is synchronous - this is why here we put it to async dispatch.
        
        __block KAppConfigResults result;
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        dispatch_async(queue, ^{
            
            // Connect to MobiControl using App Config that has been installed during MDM enrollment (agentless enrollment).
            result = [self.agentSdkCore connectToDSUsingAppConfig];
            
            // Update UI
            // UI has to be updated from main queue. This is why GCD block is here.
            dispatch_async( dispatch_get_main_queue(), ^{
                
                NSString *resultStr = @"";
                switch (result) {
                    case KAppConfigInitiationSuccess:
                        resultStr = @"Connected Successfully Using App Config";
                        break;
                    case KAppConfigNotFound:
                        resultStr = (@"App Config not found");
                        break;
                    case KAppConfigDeviceLessThanIOS7:
                        resultStr = @"App Config is not supported for this iOS version";
                        break;
                    default:
                        break;
                }
                // Update UI
                self.callbackUpdateUI([NSString stringWithUTF8String:__FUNCTION__]);
                self.callbackUpdateStatus(resultStr);
            });
        });
    }
}

// Performs disconnect from MobiControl operation
- (void)disconnectFromMobiControl {
    // Update UI
    self.callbackUpdateStatus(@"Disconnecting...");
    
    // Disconnect from MobiControl
    [self.agentSdkCore disconnect];
    
    // update UI
    self.callbackUpdateUI([NSString stringWithUTF8String:__FUNCTION__]);
}


@end
