/*************************************************************************
*
* ADOBE CONFIDENTIAL
* ___________________
*
* Copyright 2015 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/

/*jslint vars: true, node: true, plusplus: true, unparam: true, nomen: true */
/*global GLOBAL */

'use strict';

var ref = require('ref');
var ffi = require('ffi');
var xml2js = require('xml2js');

/**
    Wrapping the C API
**/

// Type Defs
var IMSRefPtr        = ref.refType('void');
var ClientContextPtr = ref.refType('void');
var StringPtr        = ref.refType('string');
var IMSStatus        = 'int';
var HTTPCallbackFn   = ffi.Function('void', [IMSStatus, 'string', ClientContextPtr]);

// Enum for IMS_releaseData
var IMS_TYPE = {
    ACCOUNTS: 0,
    PROXY_DATA: 1,
    DEVICE_ID: 2,
    DEFAULT_USER_DATA: 3,
    UNKNOWN_DATA: 0xFFFF
};

// Enum for IMS_registerClientToGroup/IMS_deregisterClientFromGroup
var IMS_BUDDY_GROUP = {
    AAM: 0
};

var FUNCTION_DEFINITIONS = {
    'IMS_createRef':                            [IMSRefPtr, ['pointer', 'int']],
    'IMS_createRefEx':                          [IMSRefPtr, ['pointer', 'string']],
    'IMS_createRefForProductVersion':           [IMSRefPtr, ['pointer', 'string']],
    'IMS_releaseRef':                           [IMSStatus, ['pointer']],
    'IMS_fetchAccessToken':                     [IMSStatus, [IMSRefPtr, 'string', 'string', 'string', 'string', 'string', HTTPCallbackFn]],
    'IMS_fetchAccessToken2':                    [IMSStatus, [IMSRefPtr, 'string', HTTPCallbackFn]],
    'IMS_fetchIDPResponseForKey':               [IMSStatus, [IMSRefPtr, 'string', HTTPCallbackFn]],
    'IMS_revokeDeviceToken':                    [IMSStatus, [IMSRefPtr, 'string', 'string', 'string', HTTPCallbackFn]],
    'IMS_fetchAccounts':                        [IMSStatus, [IMSRefPtr, 'string', StringPtr]],
    'IMS_releaseData':                          [IMSStatus, [IMSRefPtr, 'int', 'pointer']],
    'IMS_fetchUserProfileData':                 [IMSStatus, [IMSRefPtr, 'string', StringPtr]],
    'IMS_fetchDefaultUserInfoForClientId':      [IMSStatus, [IMSRefPtr, 'string', StringPtr]],
    'IMS_setProxyCredentials':                  [IMSStatus, ['string', 'string']],
    'IMS_setProxyCredentialsInIMSLibSession':   [IMSStatus, [IMSRefPtr, 'string', 'string', 'int']],
    'IMS_getProxyCredentialsFromIMSLibSession': [IMSStatus, [IMSRefPtr, StringPtr]],
    'IMS_fetchContinueToken':                   [IMSStatus, [IMSRefPtr, 'string', 'string', 'string', 'string', 'string', 'string', HTTPCallbackFn]],
    'IMS_EEPLogin':                             [IMSStatus, [IMSRefPtr, 'string', HTTPCallbackFn]],
    'IMS_setUserAsDefaultForClientId':          [IMSStatus, [IMSRefPtr, 'string', 'string']],
    'IMS_getDeviceID':                          [IMSStatus, [IMSRefPtr, StringPtr]],
    'IMS_logOutUserForClient':                  [IMSStatus, [IMSRefPtr, 'string', 'string', HTTPCallbackFn]],
    'IMS_registerClientToGroup':                [IMSStatus, [IMSRefPtr, 'string', 'int']],
    'IMS_deregisterClientFromGroup':            [IMSStatus, [IMSRefPtr, 'string', 'int']],
    'IMS_fetchFeatureFlags':                    [IMSStatus, [IMSRefPtr, 'string', 'string', 'string', HTTPCallbackFn]],
    'IMS_fetchReleaseFlag':                     [IMSStatus, [IMSRefPtr, 'string', 'string', HTTPCallbackFn]],
    'IMS_setRetryAfterResponseHandlingData':    [IMSStatus, [IMSRefPtr, 'int', 'int']]
};


function loadIMSLib(path) {
    return ffi.Library(path, FUNCTION_DEFINITIONS);
}


/**
    Handling callbacks - we need a wrapper to avoid things getting garbage collected
**/

var callbacks = [];

function createHTTPCallbackFn(callback) {
    var cb = ffi.Callback('void', [IMSStatus, 'string', ClientContextPtr], callback);
    callbacks.push(cb);
    return cb;
}

function releaseHTTPCallbackFn(cb) {
    var index = callbacks.indexOf(cb);
    if (index !== -1) {
        callbacks.splice(index, 1);
    }
}


/**
    Interface
**/

module.exports = {
    loadIMSLib: loadIMSLib,
    IMS_TYPE: IMS_TYPE,
    IMS_BUDDY_GROUP: IMS_BUDDY_GROUP,
    createHTTPCallbackFn: createHTTPCallbackFn,
    releaseHTTPCallbackFn: releaseHTTPCallbackFn
};
