/**************************************************************************************************
 *
 * ADOBE SYSTEMS INCORPORATED
 * Copyright 2015 Adobe Systems Incorporated
 * All Rights Reserved.
 *
 * NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the
 * terms of the Adobe license agreement accompanying it.  If you have received this file from a
 * source other than Adobe, then your use, modification, or distribution of it requires the prior
 * written permission of Adobe.
 *
 **************************************************************************************************/
/*jslint vars: true, node: true, plusplus: true, unparam: true, nomen: true */
/*global GLOBAL */
module.exports.init = function init() {
    'use strict';
    var exports = {};
    var utils = require('./utils');
    var  { URL }  = require('url');
    var os = require('os');
    var proxyresolverwin = require ('../build/Release/ProxyResolverWin.node');

    function initProxyResolverWindows() {
        //OS versions for windows.
        //https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832(v=vs.85).aspx
        //http://blogs.msdn.com/b/astebner/archive/2007/03/14/mailbag-what-version-of-the-net-framework-is-included-in-what-version-of-the-os.aspx
        exports.getNegotiateToken = function (spn, username, password, domain, callback) {
            proxyresolverwin.GenerateNegotiateToken({spn, username, password, domain}, function (data) {
                callback(data.error, data.data, data.more);
            });
        };

        exports.setSettingsChangedCallback = function (callback) {
            proxyresolverwin.StartListeningForProxySettingsChanges(function callbackHandler(message) {
                if (message === 'changed') {
                    callback();
                } else {
                    utils.log(utils.logLevel.WARNING, 'Error from the proxy detecting worker ' + message);
                }
            });
        };

        exports.unsetSettingsChangedCallback = proxyresolverwin.StopListeningForProxySettingsChanges;

        exports.resolve = function (url, callback) {
            proxyresolverwin.ProxiesForURL({input:url}, function callbackHandler(proxy) {
                var parsedProxyURL;
                let parsedInputURL;
                try {
                    parsedInputURL = new URL(url);
                } catch (e) {
                    utils.log(utils.logLevel.WARNING, `Unable to parse url (${url}).`);
                    return callback('Error parsing input url.');
                }
                var needToAppendProtocol = false;
                try {
                    parsedProxyURL = new URL(proxy);
                } catch (e) {
                    if (e.code === 'ERR_INVALID_URL') {
                        needToAppendProtocol = true;
                    }
                }
                if (needToAppendProtocol || parsedProxyURL.host === '') {
                    proxy = parsedInputURL.protocol + '//' + proxy;
                    try {
                        parsedProxyURL = new URL(proxy);
                    } catch (e) {
                        // Possibly something wrong with the format of the specified proxy URL, return no proxy.
                        utils.log(utils.logLevel.WARNING, `Incorrect Proxy URL (${proxy}), defaulting to no proxy.`);
                        return callback('Error parsing configured proxy URL.');
                    }
                }
                if (parsedProxyURL.href === parsedInputURL.href){
                   parsedProxyURL = {};
                } else {
                    if (parsedInputURL.protocol === 'http:') {
                        parsedProxyURL.port = parsedProxyURL.port || 80;
                    } else if (parsedInputURL.protocol === 'https:') {
                        parsedProxyURL.port = parsedProxyURL.port || 443;
                    }
                }

                callback(null,[parsedProxyURL]);
            });
        };

        exports.getRootCA = function (callback) {
            let certs = proxyresolverwin.SystemRootCA(['AuthRoot', 'Root', 'CA']);
            var returnArray = [];
            certs.forEach(function (pem) {
                if (returnArray.indexOf(pem) === -1) {
                    returnArray.push(pem);
                }
            });
            callback(null, returnArray);
        };

        exports.getOSLocale = function (callback) {
            proxyresolverwin.GetOSLocale(function (locale) {
                callback(null, locale);
            });
        };

        exports.isLocalhostProxied = proxyresolverwin.LocalhostProxied;

        exports.getLocalhostPacProxyStatus = function (callback) {
            proxyresolverwin.PacProxyStatus(function (status) {
                if (['pacFileNoProxy', 'noPacFile', 'proxied'].indexOf(status) === -1) {
                    utils.log(utils.logLevel.WARNING, 'Error fetching pac content');
                    status = 'noPacFile';
                }
                callback(status);
            });
        };
    }

    var release = os.release().split('.');
    initProxyResolverWindows();
    return exports;
}
