/*
 * Copyright 2007-2017 Charles du Jeu - Abstrium SAS <team (at) pyd.io>
 * This file is part of Pydio.
 *
 * Pydio is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Pydio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Pydio.  If not, see <http://www.gnu.org/licenses/>.
 *
 * The latest code can be found at <https://pydio.com>.
 */
'use strict';

exports.__esModule = true;

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

var _utilXMLUtils = require('../util/XMLUtils');

var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils);

/**
 * API Client
 */

var PydioApi = (function () {
    function PydioApi() {
        _classCallCheck(this, PydioApi);
    }

    PydioApi.prototype.setPydioObject = function setPydioObject(pydioObject) {
        this._pydioObject = pydioObject;
        this._baseUrl = pydioObject.Parameters.get('serverAccessPath');
    };

    PydioApi.prototype.request = function request(parameters) {
        var onComplete = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
        var onError = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];
        var settings = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];

        // Connexion already handles secure_token
        var c = new Connexion();
        if (settings.discrete) {
            c.discrete = true;
        }
        c.setParameters(parameters);
        if (settings.method) {
            c.setMethod(settings.method);
        }
        if (!onComplete) {
            onComplete = (function (transport) {
                if (transport.responseXML) return this.parseXmlMessage(transport.responseXML);
            }).bind(this);
        }
        c.onComplete = onComplete;
        if (settings.async === false) {
            c.sendSync();
        } else {
            c.sendAsync();
        }
    };

    PydioApi.prototype.loadFile = function loadFile(filePath) {
        var onComplete = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
        var onError = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];

        var c = new Connexion(filePath);
        c.setMethod('GET');
        c.onComplete = onComplete;
        c.sendAsync();
    };

    /**
     * 
     * @param file
     * @param fileParameterName
     * @param queryStringParams
     * @param onComplete
     * @param onError
     * @param onProgress
     * @returns XHR Handle to abort transfer
     */

    PydioApi.prototype.uploadFile = function uploadFile(file, fileParameterName) {
        var queryStringParams = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2];
        var onComplete = arguments.length <= 3 || arguments[3] === undefined ? function () {} : arguments[3];
        var onError = arguments.length <= 4 || arguments[4] === undefined ? function () {} : arguments[4];
        var onProgress = arguments.length <= 5 || arguments[5] === undefined ? function () {} : arguments[5];
        var uploadUrl = arguments.length <= 6 || arguments[6] === undefined ? '' : arguments[6];
        var xhrSettings = arguments.length <= 7 || arguments[7] === undefined ? {} : arguments[7];

        if (!uploadUrl) {
            uploadUrl = pydio.Parameters.get('ajxpServerAccess');
        }
        if (queryStringParams) {
            uploadUrl += (uploadUrl.indexOf('?') === -1 ? '?' : '&') + queryStringParams;
        }

        if (window.Connexion) {
            var _ret = (function () {
                // Warning, avoid double error
                var errorSent = false;
                var localError = function localError(xhr) {
                    if (!errorSent) onError('Request failed with status :' + xhr.status);
                    errorSent = true;
                };
                var c = new Connexion();
                return {
                    v: c.uploadFile(file, fileParameterName, uploadUrl, onComplete, localError, onProgress, xhrSettings)
                };
            })();

            if (typeof _ret === 'object') return _ret.v;
        }
    };

    /**
     *
     * @param userSelection UserSelection A Pydio DataModel with selected files
     * @param prototypeHiddenForm Element A hidden form element: currently relying on PrototypeJS.
     * @param dlActionName String Action name to trigger, download by default.
     * @param additionalParameters Object Optional set of key/values to pass to the download.
     */

    PydioApi.prototype.downloadSelection = function downloadSelection(userSelection) {
        var dlActionName = arguments.length <= 1 || arguments[1] === undefined ? 'download' : arguments[1];
        var additionalParameters = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

        var ajxpServerAccess = this._pydioObject.Parameters.get("ajxpServerAccess");
        var agent = navigator.userAgent || '';
        var agentIsMobile = agent.indexOf('iPhone') != -1 || agent.indexOf('iPod') != -1 || agent.indexOf('iPad') != -1 || agent.indexOf('iOs') != -1;
        var hiddenForm = pydio && pydio.UI && pydio.UI.hasHiddenDownloadForm();
        if (agentIsMobile || !hiddenForm) {
            var downloadUrl = ajxpServerAccess + '&get_action=' + dlActionName;
            if (additionalParameters) {
                for (var param in additionalParameters) {
                    if (additionalParameters.hasOwnProperty(param)) downloadUrl += "&" + param + "=" + additionalParameters[param];
                }
            }
            if (userSelection) {
                downloadUrl = userSelection.updateFormOrUrl(null, downloadUrl);
            }
            document.location.href = downloadUrl;
        } else {

            var parameters = _extends({}, additionalParameters, { secure_token: this._pydioObject.Parameters.get("SECURE_TOKEN"), get_action: dlActionName });
            var minisite_session = PydioApi.detectMinisiteSession(ajxpServerAccess);
            if (minisite_session) {
                parameters['minisite_session'] = minisite_session;
            }
            try {
                pydio.UI.sendDownloadToHiddenForm(userSelection, parameters);
            } catch (e) {
                if (window.console) window.console.error("Error while submitting hidden form for download", e);
            }
        }
    };

    PydioApi.prototype.postPlainTextContent = function postPlainTextContent(filePath, content, finishedCallback) {

        this.request({
            get_action: 'put_content',
            file: filePath,
            content: content
        }, (function (transport) {
            var success = this.parseXmlMessage(transport.responseXML);
            finishedCallback(success);
        }).bind(this), function () {
            finishedCallback(false);
        });
    };

    /**
     * Detect a minisite_session parameter in the URL
     * @param serverAccess
     * @returns string|bool
     */

    PydioApi.detectMinisiteSession = function detectMinisiteSession(serverAccess) {
        var regex = new RegExp('.*?[&\\?]' + 'minisite_session' + '=(.*?)&?.*?');
        var val = serverAccess.replace(regex, "$1");
        return val === serverAccess ? false : val;
    };

    /**
     * Detects if current browser supports HTML5 Upload.
     * @returns boolean
     */

    PydioApi.supportsUpload = function supportsUpload() {
        if (window.Connexion) {
            return window.FormData || window.FileReader;
        } else if (window.jQuery) {
            return window.FormData;
        }
        return false;
    };

    /**
     * Instanciate a PydioApi client if it's not already instanciated and return it.
     * @returns PydioApi
     */

    PydioApi.getClient = function getClient() {
        if (PydioApi._PydioClient) return PydioApi._PydioClient;
        var client = new PydioApi();
        PydioApi._PydioClient = client;
        return client;
    };

    /**
     * Load a javascript library
     * @param fileName String
     * @param onLoadedCode Function Callback
     * @param aSync Boolean load library asynchroneously
     */

    PydioApi.loadLibrary = function loadLibrary(fileName, onLoadedCode, aSync) {
        if (window.pydio && pydio.Parameters.get("ajxpVersion") && fileName.indexOf("?") == -1) {
            fileName += "?v=" + pydio.Parameters.get("ajxpVersion");
        }
        PydioApi._libUrl = false;
        if (window.pydio && pydio.Parameters.get('SERVER_PREFIX_URI')) {
            PydioApi._libUrl = pydio.Parameters.get('SERVER_PREFIX_URI');
        }

        var conn = new Connexion();
        conn._libUrl = false;
        if (pydio.Parameters.get('SERVER_PREFIX_URI')) {
            conn._libUrl = pydio.Parameters.get('SERVER_PREFIX_URI');
        }
        conn.loadLibrary(fileName, onLoadedCode, aSync);
    };

    PydioApi.prototype.switchRepository = function switchRepository(repositoryId, completeCallback) {
        var params = {
            get_action: 'switch_repository',
            repository_id: repositoryId
        };
        this.request(params, completeCallback);
    };

    PydioApi.prototype.switchLanguage = function switchLanguage(lang, completeCallback) {
        var params = {
            get_action: 'get_i18n_messages',
            lang: lang,
            format: 'json'
        };
        this.request(params, completeCallback);
    };

    PydioApi.prototype.loadXmlRegistry = function loadXmlRegistry(completeCallback) {
        var xPath = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];

        var params = { get_action: 'get_xml_registry' };
        if (xPath) params[xPath] = xPath;
        this.request(params, completeCallback);
    };

    PydioApi.prototype.getBootConf = function getBootConf(completeCallback) {
        var params = { get_action: 'get_boot_conf' };
        var cB = (function (transport) {
            if (transport.responseJSON && transport.responseJSON.SECURE_TOKEN) {
                this._pydioObject.Parameters.set('SECURE_TOKEN', transport.responseJSON.SECURE_TOKEN);
                Connexion.updateServerAccess(this._pydioObject.Parameters);
            }
            if (completeCallback) {
                completeCallback(transport);
            }
        }).bind(this);
        this.request(params, cB);
    };

    PydioApi.prototype.userSavePreference = function userSavePreference(prefName, prefValue) {
        this.request({ get_action: "save_user_pref", "pref_name_0": prefName, "pref_value_0": prefValue }, null, null, { discrete: true, method: 'post' });
    };

    PydioApi.prototype.userSavePreferences = function userSavePreferences(preferences, completeCallback) {
        var params = { 'get_action': 'save_user_pref' };
        var i = 0;
        preferences.forEach(function (value, key) {
            params["pref_name_" + i] = key;
            params["pref_value_" + i] = value;
            i++;
        });
        this.request(params, completeCallback, null, { discrete: true, method: 'post' });
    };

    PydioApi.prototype.userSavePassword = function userSavePassword(oldPass, newPass, seed, completeCallback) {
        this.request({
            get_action: 'save_user_pref',
            pref_name_0: "password",
            pref_value_0: newPass,
            crt: oldPass,
            pass_seed: seed
        }, completeCallback, null, { discrete: true, method: 'post' });
    };

    PydioApi.prototype.buildUserAvatarUrl = function buildUserAvatarUrl(userId) {
        var avatarId = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];

        if (avatarId) {
            return this._pydioObject.Parameters.get('ajxpServerAccess') + "&get_action=get_binary_param&binary_id=" + avatarId + "&user_id=" + userId;
        } else {
            return null;
        }
    };

    PydioApi.prototype.applyCheckHook = function applyCheckHook(node, hookName, hookArg, completeCallback, additionalParams) {
        var params = {
            get_action: "apply_check_hook",
            file: node.getPath(),
            hook_name: hookName,
            hook_arg: hookArg
        };
        if (additionalParams) {
            params = LangUtils.objectMerge(params, additionalParams);
        }
        this.request(params, completeCallback, null, { async: false });
    };

    /**
     * Standard parser for server XML answers
     * @param xmlResponse DOMDocument
     */

    PydioApi.prototype.parseXmlMessage = function parseXmlMessage(xmlResponse) {
        if (xmlResponse == null || xmlResponse.documentElement == null) return null;
        var childs = xmlResponse.documentElement.childNodes;
        var reloadNodes = [],
            error = false;
        this.LAST_ERROR_ID = null;

        for (var i = 0; i < childs.length; i++) {
            var child = childs[i];
            if (child.tagName === "message") {
                var messageTxt = "No message";
                if (child.firstChild) messageTxt = child.firstChild.nodeValue;
                if (child.getAttribute('type') == 'ERROR') {
                    Logger.error(messageTxt);
                    error = true;
                } else {
                    Logger.log(messageTxt);
                }
            } else if (child.tagName === "prompt") {

                if (pydio && pydio.UI && pydio.UI.openPromptDialog) {
                    var jsonData = _utilXMLUtils2['default'].XPathSelectSingleNode(childs[i], "data").firstChild.nodeValue;
                    pydio.UI.openPromptDialog(JSON.parse(jsonData));
                }
                return false;
            } else if (child.tagName == "reload_instruction") {

                var obName = child.getAttribute('object');
                if (obName === 'data') {
                    var node = child.getAttribute('node');
                    if (node) {
                        reloadNodes.push(node);
                    } else {
                        var file = child.getAttribute('file');
                        if (file) {
                            this._pydioObject.getContextHolder().setPendingSelection(file);
                        }
                        reloadNodes.push(this._pydioObject.getContextNode());
                    }
                } else if (obName == 'repository_list') {
                    this._pydioObject.reloadRepositoriesList();
                }
            } else if (child.nodeName == 'nodes_diff') {

                var dm = this._pydioObject.getContextHolder();
                if (dm.getAjxpNodeProvider().parseAjxpNodesDiffs) {
                    dm.getAjxpNodeProvider().parseAjxpNodesDiffs(childs[i], dm, this._pydioObject.user.activeRepository, !window.currentLightBox);
                }
            } else if (child.tagName == "logging_result") {

                if (child.getAttribute("secure_token")) {

                    this._pydioObject.Parameters.set('SECURE_TOKEN', child.getAttribute("secure_token"));
                    Connexion.updateServerAccess(this._pydioObject.Parameters);
                }
                var result = child.getAttribute('value');
                var errorId = false;
                switch (result) {
                    case '1':
                        this._pydioObject.loadXmlRegistry();
                        break;
                    case '0':
                    case '-1':
                        errorId = 285;
                        break;
                    case '2':
                        this._pydioObject.loadXmlRegistry();
                        break;
                    case '-2':
                        errorId = 285;
                        break;
                    case '-3':
                        errorId = 366;
                        break;
                    case '-4':
                        errorId = 386;
                        break;
                }
                if (errorId) {
                    error = true;
                    this.LAST_ERROR_ID = errorId;
                    Logger.error(this._pydioObject.MessageHash[errorId]);
                }
            } else if (child.tagName == "trigger_bg_action") {

                var _name = child.getAttribute("name");
                var messageId = child.getAttribute("messageId");
                var parameters = {};
                var callback = undefined;
                for (var j = 0; j < child.childNodes.length; j++) {
                    var paramChild = child.childNodes[j];
                    if (paramChild.tagName == 'param') {

                        parameters[paramChild.getAttribute("name")] = paramChild.getAttribute("value");
                    } else if (paramChild.tagName == 'clientCallback' && paramChild.firstChild && paramChild.firstChild.nodeValue) {

                        var callbackCode = paramChild.firstChild.nodeValue;
                        callback = new Function(callbackCode);
                    }
                }
                if (_name == "javascript_instruction" && callback) {
                    callback();
                }
            }
        }
        this._pydioObject.notify("response.xml", xmlResponse);
        if (reloadNodes.length) {
            this._pydioObject.getContextHolder().multipleNodesReload(reloadNodes);
        }
        return !error;
    };

    /**
     * Submits a form using Connexion class.
     * @param formName String The id of the form
     * @param post Boolean Whether to POST or GET
     * @param completeCallback Function Callback to be called on complete
     */

    PydioApi.prototype.submitForm = function submitForm(formName) {
        var post = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1];
        var completeCallback = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];

        var params = {};
        // TODO: UI IMPLEMENTATION
        $(formName).getElements().each(function (fElement) {
            var fValue = fElement.getValue();
            if (fElement.name == 'get_action' && fValue.substr(0, 4) == 'http') {
                fValue = PathUtils.getBasename(fValue);
            }
            if (fElement.type == 'radio' && !fElement.checked) return;
            if (params[fElement.name] && fElement.name.endsWith('[]')) {
                var existing = params[fElement.name];
                if (typeof existing == 'string') existing = [existing];
                existing.push(fValue);
                params[fElement.name] = existing;
            } else {
                params[fElement.name] = fValue;
            }
        });
        if (this._pydioObject.getContextNode()) {
            params['dir'] = this._pydioObject.getContextNode().getPath();
        }
        var onComplete = undefined;
        if (completeCallback) {
            onComplete = completeCallback;
        } else {
            onComplete = (function (transport) {
                this.parseXmlMessage(transport.responseXML);
            }).bind(this);
        }
        this.request(params, onComplete, null, { method: post ? 'post' : 'get' });
    };

    PydioApi.prototype.postSelectionWithAction = function postSelectionWithAction(actionName) {
        var callback = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
        var selectionModel = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];
        var additionalParameters = arguments.length <= 3 || arguments[3] === undefined ? null : arguments[3];

        if (!selectionModel) {
            selectionModel = this._pydioObject.getContextHolder();
        }
        var params = {
            get_action: actionName,
            dir: selectionModel.getContextNode().getPath()
        };
        params['nodes[]'] = selectionModel.getFileNames();
        if (additionalParameters) {
            params = Object.assign(params, additionalParameters);
        }
        this.request(params, callback);
    };

    /**
     * Trigger a simple download
     * @param url String
     */

    PydioApi.triggerDownload = function triggerDownload(url) {
        document.location.href = url;
    };

    return PydioApi;
})();

exports['default'] = PydioApi;
module.exports = exports['default'];
