'use strict';

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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

(function (global) {

    /**
     * React Mixin for Form Element
     */
    var FormMixin = {

        propTypes: {
            attributes: React.PropTypes.object.isRequired,
            name: React.PropTypes.string.isRequired,

            displayContext: React.PropTypes.oneOf(['form', 'grid']),
            disabled: React.PropTypes.bool,
            multiple: React.PropTypes.bool,
            value: React.PropTypes.any,
            onChange: React.PropTypes.func,
            onChangeEditMode: React.PropTypes.func,
            binary_context: React.PropTypes.string,
            errorText: React.PropTypes.string
        },

        getDefaultProps: function getDefaultProps() {
            return {
                displayContext: 'form',
                disabled: false
            };
        },

        isDisplayGrid: function isDisplayGrid() {
            return this.props.displayContext == 'grid';
        },

        isDisplayForm: function isDisplayForm() {
            return this.props.displayContext == 'form';
        },

        toggleEditMode: function toggleEditMode() {
            if (this.isDisplayForm()) return;
            var newState = !this.state.editMode;
            this.setState({ editMode: newState });
            if (this.props.onChangeEditMode) {
                this.props.onChangeEditMode(newState);
            }
        },

        enterToToggle: function enterToToggle(event) {
            if (event.key == 'Enter') {
                this.toggleEditMode();
            }
        },

        bufferChanges: function bufferChanges(newValue, oldValue) {
            this.props.onChange(newValue, oldValue);
        },

        onChange: function onChange(event, value) {
            if (value === undefined) value = event.currentTarget.getValue();
            if (this.changeTimeout) {
                global.clearTimeout(this.changeTimeout);
            }
            var newValue = value,
                oldValue = this.state.value;
            if (this.props.skipBufferChanges) {
                this.props.onChange(newValue, oldValue);
            }
            this.setState({
                dirty: true,
                value: newValue
            });
            if (!this.props.skipBufferChanges) {
                this.changeTimeout = global.setTimeout((function () {
                    this.bufferChanges(newValue, oldValue);
                }).bind(this), 250);
            }
        },

        componentWillReceiveProps: function componentWillReceiveProps(newProps) {
            var choices;
            if (newProps.attributes['choices']) {
                if (newProps.attributes['choices'] != this.props.attributes['choices']) {
                    choices = this.loadExternalValues(newProps.attributes['choices']);
                } else {
                    choices = this.state.choices;
                }
            }
            this.setState({
                value: newProps.value,
                dirty: false,
                choices: choices
            });
        },

        getInitialState: function getInitialState() {
            var choices;
            if (this.props.attributes['choices']) {
                choices = this.loadExternalValues(this.props.attributes['choices']);
            }
            return {
                editMode: false,
                dirty: false,
                value: this.props.value,
                choices: choices
            };
        },

        loadExternalValues: function loadExternalValues(choices) {
            var list_action;
            if (choices instanceof Map) {
                return choices;
            }
            var output = new Map();
            if (choices.indexOf('json_list:') === 0) {
                list_action = choices.replace('json_list:', '');
                output.set('0', pydio.MessageHash['ajxp_admin.home.6']);
                PydioApi.getClient().request({ get_action: list_action }, (function (transport) {
                    var list = transport.responseJSON.LIST;
                    var newOutput = new Map();
                    if (transport.responseJSON.HAS_GROUPS) {
                        for (key in list) {
                            if (list.hasOwnProperty(key)) {
                                // TODO: HANDLE OPTIONS GROUPS
                                for (var index = 0; index < list[key].length; index++) {
                                    newOutput.set(key + '-' + index, list[key][index].action);
                                }
                            }
                        }
                    } else {
                        for (var key in list) {
                            if (list.hasOwnProperty(key)) {
                                newOutput.set(key, list[key]);
                            }
                        }
                    }
                    this.setState({ choices: newOutput });
                }).bind(this));
            } else if (choices.indexOf('json_file:') === 0) {
                list_action = choices.replace('json_file:', '');
                output.set('0', pydio.MessageHash['ajxp_admin.home.6']);
                PydioApi.getClient().loadFile(list_action, (function (transport) {
                    var newOutput = new Map();
                    transport.responseJSON.each(function (entry) {
                        newOutput.set(entry.key, entry.label);
                    });
                    this.setState({ choices: newOutput });
                }).bind(this));
            } else if (choices == "AJXP_AVAILABLE_LANGUAGES") {
                var object = global.pydio.Parameters.get("availableLanguages");
                for (var key in object) {
                    if (object.hasOwnProperty(key)) {
                        output.set(key, object[key]);
                    }
                }
            } else if (choices == "AJXP_AVAILABLE_REPOSITORIES") {
                if (global.pydio.user) {
                    global.pydio.user.repositories.forEach(function (repository) {
                        output.set(repository.getId(), repository.getLabel());
                    });
                }
            } else {
                // Parse string and return map
                choices.split(",").map(function (choice) {
                    var label, value;
                    var l = choice.split('|');
                    if (l.length > 1) {
                        value = l[0];label = l[1];
                    } else {
                        value = label = choice;
                    }
                    if (global.pydio.MessageHash[label]) label = global.pydio.MessageHash[label];
                    output.set(value, label);
                });
            }
            return output;
        }

    };

    /**
     * React Mixin for the form helper : default properties that
     * helpers can receive
     */
    var HelperMixin = {
        propTypes: {
            paramName: React.PropTypes.string,
            paramAttributes: React.PropTypes.object,
            values: React.PropTypes.object,
            updateCallback: React.PropTypes.func
        }
    };

    /**
     * Text input, can be single line, multiLine, or password, depending on the
     * attributes.type key.
     */
    var InputText = React.createClass({
        displayName: 'InputText',

        mixins: [FormMixin],

        render: function render() {
            if (this.isDisplayGrid() && !this.state.editMode) {
                var value = this.state.value;
                return React.createElement(
                    'div',
                    { onClick: this.props.disabled ? function () {} : this.toggleEditMode, className: value ? '' : 'paramValue-empty' },
                    !value ? 'Empty' : value
                );
            } else {
                return React.createElement(
                    'span',
                    null,
                    React.createElement(ReactMUI.TextField, {
                        floatingLabelText: this.isDisplayForm() ? this.props.attributes.label : null,
                        value: this.state.value,
                        onChange: this.onChange,
                        onKeyDown: this.enterToToggle,
                        type: this.props.attributes['type'] == 'password' ? 'password' : null,
                        multiLine: this.props.attributes['type'] == 'textarea',
                        disabled: this.props.disabled,
                        errorText: this.props.errorText
                    })
                );
            }
        }

    });

    var ValidPassword = React.createClass({
        displayName: 'ValidPassword',

        mixins: [FormMixin],

        isValid: function isValid() {
            return this.state.value && this.checkMinLength(this.state.value);
        },

        checkMinLength: function checkMinLength(value) {
            var minLength = parseInt(global.pydio.getPluginConfigs("core.auth").get("PASSWORD_MINLENGTH"));
            return !(value && value.length < minLength);
        },

        getMessage: function getMessage(messageId) {
            if (this.context && this.context.getMessage) {
                return this.context.getMessage(messageId, '');
            } else if (global.pydio && global.pydio.MessageHash) {
                return global.pydio.MessageHash[messageId];
            }
        },

        getComplexityString: function getComplexityString(value) {
            var response;
            PassUtils.checkPasswordStrength(value, (function (segment, percent) {
                var responseString;
                if (global.pydio && global.pydio.MessageHash) {
                    responseString = this.getMessage(PassUtils.Options.pydioMessages[segment]);
                } else {
                    responseString = PassUtils.Options.messages[segment];
                }
                response = {
                    segment: segment,
                    color: segment > 1 ? PassUtils.Options.colors[segment] : null,
                    responseString: responseString
                };
            }).bind(this));
            return response;
        },

        render: function render() {
            if (this.isDisplayGrid() && !this.state.editMode) {
                var value = this.state.value;
                return React.createElement(
                    'div',
                    { onClick: this.props.disabled ? function () {} : this.toggleEditMode, className: value ? '' : 'paramValue-empty' },
                    !value ? 'Empty' : value
                );
            } else {
                var errorText = this.state.errorText;
                if (this.state.value) {
                    var response = this.getComplexityString(this.state.value);
                    errorText = React.createElement(
                        'span',
                        { style: { color: response.color } },
                        response.responseString
                    );
                    if (response.segment > 1) {
                        var className = "mui-error-as-hint";
                    }
                }
                return React.createElement(
                    'span',
                    null,
                    React.createElement(ReactMUI.TextField, {
                        floatingLabelText: this.isDisplayForm() ? this.props.attributes.label : null,
                        className: className,
                        value: this.state.value,
                        onChange: this.onChange,
                        onKeyDown: this.enterToToggle,
                        type: 'password',
                        multiLine: false,
                        disabled: this.props.disabled,
                        errorText: errorText
                    })
                );
            }
        }

    });

    /**
     * Checkboxk input
     */
    var InputBoolean = React.createClass({
        displayName: 'InputBoolean',

        mixins: [FormMixin],

        getDefaultProps: function getDefaultProps() {
            return {
                skipBufferChanges: true
            };
        },

        componentDidUpdate: function componentDidUpdate() {
            // Checkbox Hack
            var boolVal = this.getBooleanState();
            if (this.refs.checkbox && !this.refs.checkbox.isChecked() && boolVal) {
                this.refs.checkbox.setChecked(true);
            } else if (this.refs.checkbox && this.refs.checkbox.isChecked() && !boolVal) {
                this.refs.checkbox.setChecked(false);
            }
        },

        onCheck: function onCheck(event) {
            var newValue = this.refs.checkbox.isChecked();
            this.props.onChange(newValue, this.state.value);
            this.setState({
                dirty: true,
                value: newValue
            });
        },

        getBooleanState: function getBooleanState() {
            var boolVal = this.state.value;
            if (typeof this.state.value == 'string') {
                boolVal = boolVal == "true";
            }
            return boolVal;
        },

        render: function render() {
            var boolVal = this.getBooleanState();
            return React.createElement(
                'span',
                null,
                React.createElement(ReactMUI.Checkbox, {
                    ref: 'checkbox',
                    defaultSwitched: boolVal,
                    disabled: this.props.disabled,
                    onCheck: this.onCheck,
                    label: this.isDisplayForm() ? this.props.attributes.label : null,
                    labelPosition: this.isDisplayForm() ? 'left' : 'right'
                })
            );
        }

    });

    /**
     * Select box input conforming to Pydio standard form parameter.
     */
    var InputSelectBox = React.createClass({
        displayName: 'InputSelectBox',

        mixins: [FormMixin],

        getDefaultProps: function getDefaultProps() {
            return {
                skipBufferChanges: true
            };
        },

        onDropDownChange: function onDropDownChange(event, index, item) {
            this.onChange(event, item.payload);
            this.toggleEditMode();
        },

        onMultipleSelectChange: function onMultipleSelectChange(joinedValue, arrayValue) {
            this.onChange(null, joinedValue);
            this.toggleEditMode();
        },

        render: function render() {
            var currentValue = this.state.value;
            var currentValueIndex = 0;
            var index = 0;
            var menuItems = [],
                multipleOptions = [],
                mandatory = true;
            if (!this.props.attributes['mandatory'] || this.props.attributes['mandatory'] != "true") {
                mandatory = false;
                menuItems.unshift({ payload: -1, text: this.props.attributes['label'] + '...' });
                index++;
            }
            var itemsMap = this.state.choices;
            itemsMap.forEach(function (value, key) {
                if (currentValue == key) currentValueIndex = index;
                menuItems.push({ payload: key, text: value });
                multipleOptions.push({ value: key, label: value });
                index++;
            });
            if (this.isDisplayGrid() && !this.state.editMode || this.props.disabled) {
                var value = this.state.value;
                if (itemsMap.get(value)) value = itemsMap.get(value);
                return React.createElement(
                    'div',
                    {
                        onClick: this.props.disabled ? function () {} : this.toggleEditMode,
                        className: value ? '' : 'paramValue-empty' },
                    !value ? 'Empty' : value,
                    '   ',
                    React.createElement('span', { className: 'icon-caret-down' })
                );
            } else {
                var hasValue = false;
                if (this.props.multiple && this.props.multiple == true) {
                    if (typeof currentValue == "string") {
                        currentValue = currentValue.split(",");
                    }
                    hasValue = currentValue.length ? true : false;
                    return React.createElement(
                        'span',
                        { className: "drop-down-with-floating-label multiple has-value" },
                        React.createElement(
                            'label',
                            { className: 'drop-down-floating-label' },
                            this.props.attributes.label
                        ),
                        React.createElement(ReactSelect, {
                            options: multipleOptions,
                            value: currentValue,
                            name: 'test',
                            delimiter: ',',
                            multi: true,
                            onChange: this.onMultipleSelectChange
                        })
                    );
                } else {
                    hasValue = currentValueIndex > 0 || mandatory;
                    return React.createElement(
                        'span',
                        { className: "drop-down-with-floating-label" + (hasValue ? " has-value" : "") },
                        React.createElement(
                            'label',
                            { className: 'drop-down-floating-label' },
                            this.props.attributes.label
                        ),
                        React.createElement(ReactMUI.DropDownMenu, {
                            menuItems: menuItems,
                            onChange: this.onDropDownChange,
                            selectedIndex: currentValueIndex,
                            autoWidth: false,
                            className: this.props.className
                        })
                    );
                }
            }
        }
    });

    /**
     * Text input that is converted to integer, and
     * the UI can react to arrows for incrementing/decrementing values
     */
    var InputInteger = React.createClass({
        displayName: 'InputInteger',

        mixins: [FormMixin],

        keyDown: function keyDown(event) {
            var inc = 0,
                multiple = 1;
            if (event.key == 'Enter') {
                this.toggleEditMode();
                return;
            } else if (event.key == 'ArrowUp') {
                inc = +1;
            } else if (event.key == 'ArrowDown') {
                inc = -1;
            }
            if (event.shiftKey) {
                multiple = 10;
            }
            var parsed = parseInt(this.state.value);
            if (isNaN(parsed)) parsed = 0;
            var value = parsed + inc * multiple;
            this.onChange(null, value);
        },

        render: function render() {
            if (this.isDisplayGrid() && !this.state.editMode) {
                var value = this.state.value;
                return React.createElement(
                    'div',
                    { onClick: this.props.disabled ? function () {} : this.toggleEditMode, className: value ? '' : 'paramValue-empty' },
                    !value ? 'Empty' : value
                );
            } else {
                var intval;
                if (this.state.value) {
                    intval = parseInt(this.state.value) + '';
                    if (isNaN(intval)) intval = this.state.value + '';
                } else {
                    intval = '0';
                }
                return React.createElement(
                    'span',
                    { className: 'integer-input' },
                    React.createElement(ReactMUI.TextField, {
                        value: intval,
                        onChange: this.onChange,
                        onKeyDown: this.keyDown,
                        disabled: this.props.disabled,
                        floatingLabelText: this.isDisplayForm() ? this.props.attributes.label : null
                    })
                );
            }
        }

    });

    /**
     * UI for displaying and uploading an image,
     * using the binaryContext string.
     */
    var InputImage = React.createClass({
        displayName: 'InputImage',

        mixins: [FormMixin],

        propTypes: {
            attributes: React.PropTypes.object,
            binary_context: React.PropTypes.string
        },

        componentWillReceiveProps: function componentWillReceiveProps(newProps) {
            var imgSrc;
            if (newProps.value && !this.state.reset) {
                if (!this.state.value || this.state.value != newProps.value) {
                    imgSrc = this.getBinaryUrl(newProps.value, this.state.temporaryBinary && this.state.temporaryBinary == newProps.value);
                }
            } else if (newProps.attributes['defaultImage']) {
                if (this.state.value) {
                    //this.setState({ value:'ajxp-remove-original' });
                }
                imgSrc = newProps.attributes['defaultImage'];
            }
            if (imgSrc) {
                this.setState({ imageSrc: imgSrc, reset: false });
            }
        },

        getInitialState: function getInitialState() {
            var imgSrc, originalBinary;
            if (this.props.value) {
                imgSrc = this.getBinaryUrl(this.props.value);
                originalBinary = this.props.value;
            } else if (this.props.attributes['defaultImage']) {
                imgSrc = this.props.attributes['defaultImage'];
            }
            return { imageSrc: imgSrc, originalBinary: originalBinary };
        },

        getBinaryUrl: function getBinaryUrl(binaryId) {
            var isTemporary = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];

            var url = global.pydio.Parameters.get('ajxpServerAccess') + "&get_action=" + this.props.attributes['loadAction'];
            if (!isTemporary) {
                url += "&binary_id=" + binaryId;
            } else {
                url += "&tmp_file=" + binaryId;
            }
            if (this.props.binary_context) {
                url += "&" + this.props.binary_context;
            }
            return url;
        },

        getUploadUrl: function getUploadUrl(paramsOnly) {
            var params = "get_action=" + this.props.attributes['uploadAction'];
            if (this.props.binary_context) {
                params += "&" + this.props.binary_context;
            }
            if (paramsOnly) {
                return params;
            } else {
                return global.pydio.Parameters.get('ajxpServerAccess') + "&" + params;
            }
        },

        uploadComplete: function uploadComplete(newBinaryName) {
            var prevValue = this.state.value;
            this.setState({
                temporaryBinary: newBinaryName,
                value: null
            });
            if (this.props.onChange) {
                var additionalFormData = { type: 'binary' };
                if (this.state.originalBinary) {
                    additionalFormData['original_binary'] = this.state.originalBinary;
                }
                this.props.onChange(newBinaryName, prevValue, additionalFormData);
            }
        },

        htmlUpload: function htmlUpload() {
            global.formManagerHiddenIFrameSubmission = (function (result) {
                result = result.trim();
                this.uploadComplete(result);
                global.formManagerHiddenIFrameSubmission = null;
            }).bind(this);
            this.refs.uploadForm.getDOMNode().submit();
        },

        onDrop: function onDrop(files, event, dropzone) {
            if (PydioApi.supportsUpload()) {
                this.setState({ loading: true });
                PydioApi.getClient().uploadFile(files[0], "userfile", this.getUploadUrl(true), (function (transport) {
                    // complete
                    var result = transport.responseText.trim().replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
                    result = result.replace('parent.formManagerHiddenIFrameSubmission("', '').replace('");', '');
                    this.uploadComplete(result);
                    this.setState({ loading: false });
                }).bind(this), function (transport) {
                    // error
                    this.setState({ loading: false });
                }, function (computableEvent) {
                    // progress
                    // console.log(computableEvent);
                });
            } else {
                    this.htmlUpload();
                }
        },

        clearImage: function clearImage() {
            if (global.confirm('Do you want to remove the current image?')) {
                var prevValue = this.state.value;
                this.setState({
                    value: 'ajxp-remove-original',
                    reset: true
                }, (function () {
                    this.props.onChange('ajxp-remove-original', prevValue, { type: 'binary' });
                }).bind(this));
            }
        },

        render: function render() {
            var coverImageStyle = {
                backgroundImage: "url(" + this.state.imageSrc + ")",
                backgroundPosition: "50% 50%",
                backgroundSize: "cover"
            };
            var icons = [];
            if (this.state && this.state.loading) {
                icons.push(React.createElement('span', { key: 'spinner', className: 'icon-spinner rotating', style: { opacity: '0' } }));
            } else {
                icons.push(React.createElement('span', { key: 'camera', className: 'icon-camera', style: { opacity: '0' } }));
            }
            return React.createElement(
                'div',
                null,
                React.createElement(
                    'div',
                    { className: 'image-label' },
                    this.props.attributes.label
                ),
                React.createElement(
                    'form',
                    { ref: 'uploadForm', encType: 'multipart/form-data', target: 'uploader_hidden_iframe', method: 'post', action: this.getUploadUrl() },
                    React.createElement(
                        FileDropzone,
                        { onDrop: this.onDrop, accept: 'image/*', style: coverImageStyle },
                        icons
                    )
                ),
                React.createElement(
                    'div',
                    { className: 'binary-remove-button', onClick: this.clearImage },
                    React.createElement('span', { key: 'remove', className: 'mdi mdi-close' }),
                    ' RESET'
                ),
                React.createElement('iframe', { style: { display: "none" }, id: 'uploader_hidden_iframe', name: 'uploader_hidden_iframe' })
            );
        }

    });

    var ActionRunnerMixin = {

        propTypes: {
            attributes: React.PropTypes.object.isRequired,
            applyButtonAction: React.PropTypes.func,
            actionCallback: React.PropTypes.func
        },

        applyAction: function applyAction(callback) {
            var choicesValue = this.props.attributes['choices'].split(":");
            var firstPart = choicesValue.shift();
            if (firstPart == "run_client_action" && global.pydio) {
                global.pydio.getController().fireAction(choicesValue.shift());
                return;
            }
            if (this.props.applyButtonAction) {
                var parameters = { get_action: firstPart };
                if (choicesValue.length > 1) {
                    parameters['action_plugin_id'] = choicesValue.shift();
                    parameters['action_plugin_method'] = choicesValue.shift();
                }
                if (this.props.attributes['name'].indexOf("/") !== -1) {
                    parameters['button_key'] = PathUtils.getDirname(this.props.attributes['name']);
                }
                this.props.applyButtonAction(parameters, callback);
            }
        }

    };

    /**
     * Simple RaisedButton executing the applyButtonAction
     */
    var InputButton = React.createClass({
        displayName: 'InputButton',

        mixins: [ActionRunnerMixin],

        applyButton: function applyButton() {

            var callback = this.props.actionCallback;
            if (!callback) {
                callback = function (transport) {
                    var text = transport.responseText;
                    if (text.startsWith('SUCCESS:')) {
                        global.pydio.displayMessage('SUCCESS', transport.responseText.replace('SUCCESS:', ''));
                    } else {
                        global.pydio.displayMessage('ERROR', transport.responseText.replace('ERROR:', ''));
                    }
                };
            }
            this.applyAction(callback);
        },

        render: function render() {
            return React.createElement(ReactMUI.RaisedButton, {
                label: this.props.attributes['label'],
                onClick: this.applyButton,
                disabled: this.props.disabled
            });
        }
    });

    var MonitoringLabel = React.createClass({
        displayName: 'MonitoringLabel',

        mixins: [ActionRunnerMixin],

        getInitialState: function getInitialState() {
            var loadingMessage = 'Loading';
            if (this.context && this.context.getMessage) {
                loadingMessage = this.context.getMessage(466, '');
            } else if (global.pydio && global.pydio.MessageHash) {
                loadingMessage = global.pydio.MessageHash[466];
            }
            return { status: loadingMessage };
        },

        componentDidMount: function componentDidMount() {
            var callback = (function (transport) {
                this.setState({ status: transport.responseText });
            }).bind(this);
            this._poller = (function () {
                this.applyAction(callback);
            }).bind(this);
            this._poller();
            this._pe = global.setInterval(this._poller, 10000);
        },

        componentWillUnmount: function componentWillUnmount() {
            if (this._pe) {
                global.clearInterval(this._pe);
            }
        },

        render: function render() {
            return React.createElement(
                'div',
                null,
                this.state.status
            );
        }

    });

    /**
     * UI to drop a file (or click to browse), used by the InputImage component.
     */
    var FileDropzone = React.createClass({
        displayName: 'FileDropzone',

        getDefaultProps: function getDefaultProps() {
            return {
                supportClick: true,
                multiple: true,
                onDrop: function onDrop() {}
            };
        },

        getInitialState: function getInitialState() {
            return {
                isDragActive: false
            };
        },

        propTypes: {
            onDrop: React.PropTypes.func.isRequired,
            size: React.PropTypes.number,
            style: React.PropTypes.object,
            supportClick: React.PropTypes.bool,
            accept: React.PropTypes.string,
            multiple: React.PropTypes.bool
        },

        onDragLeave: function onDragLeave(e) {
            this.setState({
                isDragActive: false
            });
        },

        onDragOver: function onDragOver(e) {
            e.preventDefault();
            e.dataTransfer.dropEffect = "copy";

            this.setState({
                isDragActive: true
            });
        },

        onDrop: function onDrop(e) {
            e.preventDefault();

            this.setState({
                isDragActive: false
            });

            var files;
            if (e.dataTransfer) {
                files = e.dataTransfer.files;
            } else if (e.target) {
                files = e.target.files;
            }

            var maxFiles = this.props.multiple ? files.length : 1;
            for (var i = 0; i < maxFiles; i++) {
                files[i].preview = URL.createObjectURL(files[i]);
            }

            if (this.props.onDrop) {
                files = Array.prototype.slice.call(files, 0, maxFiles);
                this.props.onDrop(files, e, this);
            }
        },

        onClick: function onClick() {
            if (this.props.supportClick === true) {
                this.open();
            }
        },

        open: function open() {
            this.refs.fileInput.getDOMNode().click();
        },

        render: function render() {

            var className = this.props.className || 'dropzone';
            if (this.state.isDragActive) {
                className += ' active';
            }

            var style = this.props.style || {
                width: this.props.size || 100,
                height: this.props.size || 100,
                borderStyle: this.state.isDragActive ? "solid" : "dashed"
            };
            if (this.props.style) {
                style = LangUtils.objectMerge(this.props.style, style);
            }

            return React.createElement(
                'div',
                { className: className, style: style, onClick: this.onClick, onDragLeave: this.onDragLeave, onDragOver: this.onDragOver, onDrop: this.onDrop },
                React.createElement('input', { style: { display: 'none' }, name: 'userfile', type: 'file', multiple: this.props.multiple, ref: 'fileInput', onChange: this.onDrop, accept: this.props.accept }),
                this.props.children
            );
        }

    });

    /**
     * Display a form companion linked to a given input.
     * Props: helperData : contains the pluginId and the whole paramAttributes
     */
    var PydioFormHelper = React.createClass({
        displayName: 'PydioFormHelper',

        propTypes: {
            helperData: React.PropTypes.object,
            close: React.PropTypes.func.isRequired
        },

        closeHelper: function closeHelper() {
            this.props.close();
        },

        render: function render() {
            var helper;
            if (this.props.helperData) {
                var helpersCache = PydioFormManager.getHelpersCache();
                var pluginHelperNamespace = helpersCache[this.props.helperData['pluginId']]['namespace'];
                helper = React.createElement(
                    'div',
                    null,
                    React.createElement(
                        'div',
                        { className: 'helper-title' },
                        React.createElement('span', { className: 'helper-close mdi mdi-close', onClick: this.closeHelper }),
                        'Pydio Companion'
                    ),
                    React.createElement(
                        'div',
                        { className: 'helper-content' },
                        React.createElement(ReactPydio.AsyncComponent, _extends({}, this.props.helperData, {
                            namespace: pluginHelperNamespace,
                            componentName: 'Helper',
                            paramName: this.props.helperData['paramAttributes']['name']
                        }))
                    )
                );
            }
            return React.createElement(
                'div',
                { className: 'pydio-form-helper' + (helper ? ' helper-visible' : ' helper-empty') },
                helper
            );
        }

    });

    /**
     * Sub form with a selector, switching its fields depending
     * on the selector value.
     */
    var GroupSwitchPanel = React.createClass({
        displayName: 'GroupSwitchPanel',

        propTypes: {
            paramAttributes: React.PropTypes.object.isRequired,
            parameters: React.PropTypes.array.isRequired,
            values: React.PropTypes.object.isRequired,
            onChange: React.PropTypes.func.isRequired
        },

        computeSubPanelParameters: function computeSubPanelParameters() {

            // CREATE SUB FORM PANEL
            // Get all values
            var switchName = this.props.paramAttributes['type'].split(":").pop();
            var switchValues = {};
            var parentName = this.props.paramAttributes['name'];
            var potentialSubSwitches = [];
            this.props.parameters.map((function (p) {
                "use strict";
                if (!p['group_switch_name']) return;
                if (p['group_switch_name'] != switchName) {
                    potentialSubSwitches.push(p);
                    return;
                }
                var crtSwitch = p['group_switch_value'];
                if (!switchValues[crtSwitch]) {
                    switchValues[crtSwitch] = {
                        label: p['group_switch_label'],
                        fields: [],
                        values: {},
                        fieldsKeys: {}
                    };
                }
                p = LangUtils.deepCopy(p);
                delete p['group_switch_name'];
                p['name'] = parentName + '/' + p['name'];
                var vKey = p['name'];
                var paramName = vKey;
                if (switchValues[crtSwitch].fieldsKeys[paramName]) {
                    return;
                }
                switchValues[crtSwitch].fields.push(p);
                switchValues[crtSwitch].fieldsKeys[paramName] = paramName;
                if (this.props.values && this.props.values[vKey]) {
                    switchValues[crtSwitch].values[paramName] = this.props.values[vKey];
                }
            }).bind(this));
            // Remerge potentialSubSwitches to each parameters set
            for (var k in switchValues) {
                if (switchValues.hasOwnProperty(k)) {
                    var sv = switchValues[k];
                    sv.fields = sv.fields.concat(potentialSubSwitches);
                }
            }

            return switchValues;
        },

        clearSubParametersValues: function clearSubParametersValues(parentName, newValue, newFields) {
            var vals = LangUtils.deepCopy(this.props.values);
            var toRemove = {};
            for (var key in vals) {
                if (vals.hasOwnProperty(key) && key.indexOf(parentName + '/') === 0) {
                    toRemove[key] = '';
                }
            }
            vals[parentName] = newValue;

            newFields.map(function (p) {
                if (p.type == 'hidden' && p['default'] && !p['group_switch_name'] || p['group_switch_name'] == parentName) {
                    vals[p['name']] = p['default'];
                    if (toRemove[p['name']] !== undefined) delete toRemove[p['name']];
                } else if (p['name'].indexOf(parentName + '/') === 0 && p['default']) {
                    if (p['type'] && p['type'].startsWith('group_switch:')) {
                        //vals[p['name']] = {group_switch_value:p['default']};
                        vals[p['name']] = p['default'];
                    } else {
                        vals[p['name']] = p['default'];
                    }
                }
            });
            this.props.onChange(vals, true, toRemove);
            //this.onParameterChange(parentName, newValue);
        },

        onChange: function onChange(newValues, dirty, removeValues) {
            this.props.onChange(newValues, true, removeValues);
        },

        render: function render() {
            var attributes = this.props.paramAttributes;
            var values = this.props.values;

            var paramName = attributes['name'];
            var switchValues = this.computeSubPanelParameters(attributes);
            var selectorValues = new Map();
            Object.keys(switchValues).map(function (k) {
                selectorValues.set(k, switchValues[k].label);
            });
            var selectorChanger = (function (newValue) {
                this.clearSubParametersValues(paramName, newValue, switchValues[newValue] ? switchValues[newValue].fields : []);
            }).bind(this);
            var subForm, selectorLegend, subFormHeader;
            var selector = React.createElement(InputSelectBox, {
                key: paramName,
                name: paramName,
                className: 'group-switch-selector',
                attributes: {
                    name: paramName,
                    choices: selectorValues,
                    label: attributes['label'],
                    mandatory: attributes['mandatory']
                },
                value: values[paramName],
                onChange: selectorChanger,
                displayContext: 'form',
                disabled: this.props.disabled,
                ref: 'subFormSelector'
            });

            var helperMark;
            if (this.props.setHelperData && this.props.checkHasHelper && this.props.checkHasHelper(attributes['name'], this.props.helperTestFor)) {
                var showHelper = (function () {
                    this.props.setHelperData({ paramAttributes: attributes, values: values });
                }).bind(this);
                helperMark = React.createElement('span', { className: 'icon-question-sign', onClick: showHelper });
            }

            selectorLegend = React.createElement(
                'div',
                { className: 'form-legend' },
                attributes['description'],
                ' ',
                helperMark
            );
            if (values[paramName] && switchValues[values[paramName]]) {
                subFormHeader = React.createElement(
                    'h4',
                    null,
                    values[paramName]
                );
                subForm = React.createElement(PydioFormPanel, {
                    onParameterChange: this.props.onParameterChange,
                    applyButtonAction: this.props.applyButtonAction,
                    disabled: this.props.disabled,
                    ref: paramName + '-SUB',
                    key: paramName + '-SUB',
                    className: 'sub-form',
                    parameters: switchValues[values[paramName]].fields,
                    values: values,
                    depth: this.props.depth + 1,
                    onChange: this.onChange,
                    checkHasHelper: this.props.checkHasHelper,
                    setHelperData: this.props.setHelperData,
                    helperTestFor: values[paramName],
                    accordionizeIfGroupsMoreThan: 5
                });
            }
            return React.createElement(
                'div',
                { className: 'sub-form-group' },
                selector,
                selectorLegend,
                subForm
            );
        }

    });

    /**
     * Sub form replicating itself (+/-)
     */
    var ReplicationPanel = React.createClass({
        displayName: 'ReplicationPanel',

        propTypes: {
            parameters: React.PropTypes.array.isRequired,
            values: React.PropTypes.object,
            onChange: React.PropTypes.func,
            disabled: React.PropTypes.bool,
            binary_context: React.PropTypes.string,
            depth: React.PropTypes.number
        },

        buildSubValue: function buildSubValue(values) {
            var index = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];

            var subVal;
            var suffix = index == 0 ? '' : '_' + index;
            this.props.parameters.map(function (p) {
                var pName = p['name'];
                if (values[pName + suffix] !== undefined) {
                    if (!subVal) subVal = {};
                    subVal[pName] = values[pName + suffix];
                }
            });
            return subVal || false;
        },

        indexedValues: function indexedValues(rowsArray) {
            var index = 0;
            var values = {};
            rowsArray.map(function (row) {
                var suffix = index == 0 ? '' : '_' + index;
                for (var p in row) {
                    if (!row.hasOwnProperty(p)) continue;
                    values[p + suffix] = row[p];
                }
                index++;
            });
            return values;
        },

        indexValues: function indexValues(rowsArray, removeLastRow) {
            var indexed = this.indexedValues(rowsArray);
            if (this.props.onChange) {
                if (removeLastRow) {
                    var lastRow = {},
                        nextIndex = rowsArray.length - 1;
                    this.props.parameters.map(function (p) {
                        lastRow[p['name'] + '_' + nextIndex] = '';
                    });
                    this.props.onChange(indexed, true, lastRow);
                } else {
                    this.props.onChange(indexed, true);
                }
            }
        },

        instances: function instances() {
            // Analyze current value to grab number of rows.
            var rows = [],
                subVal,
                index = 0;
            while (subVal = this.buildSubValue(this.props.values, index)) {
                index++;
                rows.push(subVal);
            }
            if (!rows.length) {
                var emptyValue = {};
                this.props.parameters.map(function (p) {
                    emptyValue[p['name']] = p['default'] || '';
                });
                rows.push(emptyValue);
            }
            return rows;
        },

        addRow: function addRow() {
            var newValue = {},
                currentValues = this.instances();
            this.props.parameters.map(function (p) {
                newValue[p['name']] = p['default'] || '';
            });
            currentValues.push(newValue);
            this.indexValues(currentValues);
        },

        removeRow: function removeRow(index) {
            var instances = this.instances();
            var removeInst = instances[index];
            instances = LangUtils.arrayWithout(this.instances(), index);
            instances.push(removeInst);
            this.indexValues(instances, true);
        },

        swapRows: function swapRows(i, j) {
            var instances = this.instances();
            var tmp = instances[j];
            instances[j] = instances[i];
            instances[i] = tmp;
            this.indexValues(instances);
        },

        onChange: function onChange(index, newValues, dirty) {
            var instances = this.instances();
            instances[index] = newValues;
            this.indexValues(instances);
        },

        onParameterChange: function onParameterChange(index, paramName, newValue, oldValue) {
            var instances = this.instances();
            instances[index][paramName] = newValue;
            this.indexValues(instances);
        },

        render: function render() {
            var replicationTitle, replicationDescription;
            var firstParam = this.props.parameters[0];
            replicationTitle = firstParam['replicationTitle'] || firstParam['label'];
            replicationDescription = firstParam['replicationDescription'] || firstParam['description'];

            var instances = this.instances();
            var rows = instances.map((function (subValues, index) {
                var buttons = [];
                if (instances.length > 1) {
                    if (index > 0) {
                        var upF = (function () {
                            this.swapRows(index, index - 1);
                        }).bind(this);
                        buttons.push(React.createElement(ReactMUI.IconButton, { key: 'up', iconClassName: 'icon-caret-up', onClick: upF }));
                    }
                    if (index < instances.length - 1) {
                        var downF = (function () {
                            this.swapRows(index, index + 1);
                        }).bind(this);
                        buttons.push(React.createElement(ReactMUI.IconButton, { key: 'down', iconClassName: 'icon-caret-down', onClick: downF }));
                    }
                }
                if (index != 0 || instances.length > 1) {
                    var removeF = (function () {
                        this.removeRow(index);
                    }).bind(this);
                    buttons.push(React.createElement(ReactMUI.IconButton, { key: 'remove', iconClassName: 'icon-remove-sign', onClick: removeF }));
                }
                if (!buttons.length) {
                    buttons.push(React.createElement(ReactMUI.IconButton, { key: 'remove', className: 'disabled', iconClassName: 'icon-remove-sign', disabled: true }));
                }
                var actionBar = React.createElement(
                    'div',
                    { className: 'replicable-action-bar' },
                    buttons
                );
                var onChange = (function (values, dirty) {
                    this.onChange(index, values, dirty);
                }).bind(this);
                var onParameterChange = (function (paramName, newValue, oldValue) {
                    this.onParameterChange(index, paramName, newValue, oldValue);
                }).bind(this);
                return React.createElement(PydioFormPanel, _extends({}, this.props, {
                    key: index,
                    values: subValues,
                    onChange: null,
                    onParameterChange: onParameterChange,
                    header: actionBar,
                    className: 'replicable-group',
                    depth: this.props.depth
                }));
            }).bind(this));
            return React.createElement(
                'div',
                { className: 'replicable-field' },
                React.createElement(
                    'div',
                    { className: 'title-bar' },
                    React.createElement(ReactMUI.IconButton, { key: 'add', style: { float: 'right' }, iconClassName: 'icon-plus', tooltip: 'Add value', onClick: this.addRow }),
                    React.createElement(
                        'div',
                        { className: 'title' },
                        replicationTitle
                    ),
                    React.createElement(
                        'div',
                        { className: 'legend' },
                        replicationDescription
                    )
                ),
                rows
            );
        }

    });

    /**
     * Main form constructor
     * @param parameters Set of Pydio StandardForm parameters
     * @param values Set of values (object)
     * @param onParameterChange Trigger unitary function when one form input changes.
     * @param onChange Send all form values onchange, including eventually the removed ones (for dynamic panels)
     * @param disabled
     * @param binary_context a string added to image inputs upload/downlaod operations
     * @param depth  by default 0, subform will see their zDepth increased by one.
     * @param header Add an additional header component (added inside first subpanel)
     * @param footer  Add an additional footer component (added inside last subpanel).
     * @param additionalPanes Add full panes at the top or the bottom
     * @param tabs group form panels in tabs instead of displaying multiple papers.
     * @param setHelperData Pass helper data
     * @param checkHasHelper Function to check if a given parameter has an associated helper.
     */
    var PydioFormPanel = React.createClass({
        displayName: 'PydioFormPanel',

        _hiddenValues: {},
        _internalValid: null,
        _parametersMetadata: null,

        propTypes: {
            parameters: React.PropTypes.array.isRequired,
            values: React.PropTypes.object,
            onParameterChange: React.PropTypes.func,
            onChange: React.PropTypes.func,
            onValidStatusChange: React.PropTypes.func,
            disabled: React.PropTypes.bool,
            binary_context: React.PropTypes.string,
            depth: React.PropTypes.number,

            /* Display Options */
            header: React.PropTypes.object,
            footer: React.PropTypes.object,
            additionalPanes: React.PropTypes.shape({
                top: React.PropTypes.array,
                bottom: React.PropTypes.array
            }),
            tabs: React.PropTypes.array,
            accordionizeIfGroupsMoreThan: React.PropTypes.number,
            onScrollCallback: React.PropTypes.func,

            /* Helper Options */
            setHelperData: React.PropTypes.func,
            checkHasHelper: React.PropTypes.func,
            helperTestFor: React.PropTypes.string

        },

        getDefaultProps: function getDefaultProps() {
            return { depth: 0, values: {} };
        },

        componentWillReceiveProps: function componentWillReceiveProps(newProps) {
            if (JSON.stringify(newProps.parameters) !== JSON.stringify(this.props.parameters)) {
                this._internalValid = null;
                this._hiddenValues = {};
                this._parametersMetadata = {};
            }
        },

        getValues: function getValues() {
            return this.props.values; //LangUtils.mergeObjectsRecursive(this._hiddenValues, this.props.values);
        },

        onParameterChange: function onParameterChange(paramName, newValue, oldValue) {
            var additionalFormData = arguments.length <= 3 || arguments[3] === undefined ? null : arguments[3];

            // Update writeValues
            var newValues = LangUtils.deepCopy(this.getValues());
            if (this.props.onParameterChange) {
                this.props.onParameterChange(paramName, newValue, oldValue, additionalFormData);
            }
            if (additionalFormData) {
                if (!this._parametersMetadata) this._parametersMetadata = {};
                this._parametersMetadata[paramName] = additionalFormData;
            }
            newValues[paramName] = newValue;
            var dirty = true;
            this.onChange(newValues, dirty);
        },

        onChange: function onChange(newValues, dirty, removeValues) {
            if (this.props.onChange) {
                //newValues = LangUtils.mergeObjectsRecursive(this._hiddenValues, newValues);
                for (var key in this._hiddenValues) {
                    if (this._hiddenValues.hasOwnProperty(key) && newValues[key] === undefined && (!removeValues || removeValues[key] == undefined)) {
                        newValues[key] = this._hiddenValues[key];
                    }
                }
                this.props.onChange(newValues, dirty, removeValues);
            }
            this.checkValidStatus(newValues);
        },

        onSubformChange: function onSubformChange(newValues, dirty, removeValues) {
            var values = LangUtils.mergeObjectsRecursive(this.getValues(), newValues);
            if (removeValues) {
                for (var k in removeValues) {
                    if (removeValues.hasOwnProperty(k) && values[k] !== undefined) {
                        delete values[k];
                        if (this._hiddenValues[k] !== undefined) {
                            delete this._hiddenValues[k];
                        }
                    }
                }
            }
            this.onChange(values, dirty, removeValues);
        },

        applyButtonAction: function applyButtonAction(parameters, callback) {
            if (this.props.applyButtonAction) {
                this.props.applyButtonAction(parameters, callback);
                return;
            }
            parameters = LangUtils.mergeObjectsRecursive(parameters, this.getValuesForPOST(this.getValues()));
            PydioApi.getClient().request(parameters, callback);
        },

        getValuesForPOST: function getValuesForPOST(values) {
            var prefix = arguments.length <= 1 || arguments[1] === undefined ? 'DRIVER_OPTION_' : arguments[1];

            return PydioFormManager.getValuesForPOST(this.props.parameters, values, prefix, this._parametersMetadata);
        },

        checkValidStatus: function checkValidStatus(values) {
            var failedMandatories = [];
            this.props.parameters.map(function (p) {
                if (['string', 'textarea', 'password', 'integer'].indexOf(p.type) > -1 && (p.mandatory == "true" || p.mandatory === true)) {
                    if (!values || !values.hasOwnProperty(p.name) || values[p.name] === undefined || values[p.name] === "") {
                        failedMandatories.push(p);
                    }
                }
            });
            var previousValue, newValue;
            previousValue = this._internalValid; //(this._internalValid !== undefined ? this._internalValid : true);
            newValue = failedMandatories.length ? false : true;
            if (newValue !== this._internalValid && this.props.onValidStatusChange) {
                this.props.onValidStatusChange(newValue, failedMandatories);
            }
            this._internalValid = newValue;
        },

        componentDidMount: function componentDidMount() {
            this.checkValidStatus(this.props.values);
        },

        renderGroupHeader: function renderGroupHeader(groupLabel, accordionize, index, active) {

            var properties = { key: 'group-' + groupLabel };
            if (accordionize) {
                var current = this.state && this.state.currentActiveGroup ? this.state.currentActiveGroup : null;
                properties['className'] = 'group-label-' + (active ? 'active' : 'inactive');
                properties['onClick'] = (function () {
                    this.setState({ currentActiveGroup: current != index ? index : null });
                }).bind(this);
                groupLabel = [React.createElement('span', { key: 'toggler', className: "group-active-toggler icon-angle-" + (current == index ? 'down' : 'right') }), groupLabel];
            }

            return React.createElement('h' + (3 + this.props.depth), properties, groupLabel);
        },

        render: function render() {
            var allGroups = [];
            var values = this.getValues();
            var groupsOrdered = ['__DEFAULT__'];
            allGroups['__DEFAULT__'] = { FIELDS: [] };
            var replicationGroups = {};

            this.props.parameters.map((function (attributes) {

                var type = attributes['type'];
                var paramName = attributes['name'];
                var field;
                if (attributes['group_switch_name']) return;

                var group = attributes['group'] || '__DEFAULT__';
                if (!allGroups[group]) {
                    groupsOrdered.push(group);
                    allGroups[group] = { FIELDS: [], LABEL: group };
                }

                var repGroup = attributes['replicationGroup'];
                if (repGroup) {

                    if (!replicationGroups[repGroup]) {
                        replicationGroups[repGroup] = {
                            PARAMS: [],
                            GROUP: group,
                            POSITION: allGroups[group].FIELDS.length
                        };
                        allGroups[group].FIELDS.push('REPLICATION:' + repGroup);
                    }
                    // Copy
                    var repAttr = LangUtils.deepCopy(attributes);
                    delete repAttr['replicationGroup'];
                    delete repAttr['group'];
                    replicationGroups[repGroup].PARAMS.push(repAttr);
                } else {

                    if (type.indexOf("group_switch:") === 0) {

                        field = React.createElement(GroupSwitchPanel, _extends({}, this.props, {
                            onChange: this.onSubformChange,
                            paramAttributes: attributes,
                            parameters: this.props.parameters,
                            values: this.props.values,
                            key: paramName,
                            onScrollCallback: null
                        }));
                    } else if (attributes['type'] !== 'hidden') {

                        var helperMark;
                        if (this.props.setHelperData && this.props.checkHasHelper && this.props.checkHasHelper(attributes['name'], this.props.helperTestFor)) {
                            var showHelper = (function () {
                                this.props.setHelperData({
                                    paramAttributes: attributes,
                                    values: values,
                                    postValues: this.getValuesForPOST(values),
                                    applyButtonAction: this.applyButtonAction
                                }, this.props.helperTestFor);
                            }).bind(this);
                            helperMark = React.createElement('span', { className: 'icon-question-sign', onClick: showHelper });
                        }
                        var mandatoryMissing = false;
                        var classLegend = "form-legend";
                        if (attributes['mandatory'] && (attributes['mandatory'] === "true" || attributes['mandatory'] === true)) {
                            if (['string', 'textarea', 'image', 'integer'].indexOf(attributes['type']) !== -1 && !values[paramName]) {
                                mandatoryMissing = true;
                                classLegend = "form-legend mandatory-missing";
                            }
                        }

                        var props = {
                            ref: "formElement",
                            attributes: attributes,
                            name: paramName,
                            value: values[paramName],
                            onChange: (function (newValue, oldValue, additionalFormData) {
                                this.onParameterChange(paramName, newValue, oldValue, additionalFormData);
                            }).bind(this),
                            disabled: this.props.disabled || attributes['readonly'],
                            multiple: attributes['multiple'],
                            binary_context: this.props.binary_context,
                            displayContext: 'form',
                            applyButtonAction: this.applyButtonAction,
                            errorText: mandatoryMissing ? 'Field cannot be empty' : null
                        };

                        field = React.createElement(
                            'div',
                            { key: paramName, className: 'form-entry-' + attributes['type'] },
                            PydioForm.createFormElement(props),
                            React.createElement(
                                'div',
                                { className: classLegend },
                                attributes['description'],
                                ' ',
                                helperMark
                            )
                        );
                    } else {

                        this._hiddenValues[paramName] = values[paramName] !== undefined ? values[paramName] : attributes['default'];
                    }

                    if (field) {
                        allGroups[group].FIELDS.push(field);
                    }
                }
            }).bind(this));

            for (var rGroup in replicationGroups) {
                if (!replicationGroups.hasOwnProperty(rGroup)) continue;
                var rGroupData = replicationGroups[rGroup];
                allGroups[rGroupData.GROUP].FIELDS[rGroupData.POSITION] = React.createElement(ReplicationPanel, _extends({}, this.props, {
                    key: "replication-group-" + rGroupData.PARAMS[0].name,
                    onChange: this.onSubformChange,
                    onParameterChange: null,
                    values: this.getValues(),
                    depth: this.props.depth + 1,
                    parameters: rGroupData.PARAMS,
                    applyButtonAction: this.applyButtonAction,
                    onScrollCallback: null
                }));
            }

            var groupPanes = [];
            var accordionize = this.props.accordionizeIfGroupsMoreThan && groupsOrdered.length > this.props.accordionizeIfGroupsMoreThan;
            var currentActiveGroup = this.state && this.state.currentActiveGroup ? this.state.currentActiveGroup : 0;
            groupsOrdered.map((function (g, gIndex) {
                var header,
                    gData = allGroups[g];
                var className = 'pydio-form-group',
                    active = false;
                if (accordionize) {
                    active = currentActiveGroup == gIndex;
                    if (gIndex == currentActiveGroup) className += ' form-group-active';else className += ' form-group-inactive';
                }
                if (!gData.FIELDS.length) return;
                if (gData.LABEL) header = this.renderGroupHeader(gData.LABEL, accordionize, gIndex, active);
                if (this.props.depth == 0) {
                    groupPanes.push(React.createElement(
                        ReactMUI.Paper,
                        { className: className, key: 'pane-' + g },
                        gIndex == 0 && this.props.header ? this.props.header : null,
                        header,
                        React.createElement(
                            'div',
                            null,
                            gData.FIELDS
                        ),
                        gIndex == groupsOrdered.length - 1 && this.props.footer ? this.props.footer : null
                    ));
                } else {
                    groupPanes.push(React.createElement(
                        'div',
                        { className: className, key: 'pane-' + g },
                        gIndex == 0 && this.props.header ? this.props.header : null,
                        header,
                        React.createElement(
                            'div',
                            null,
                            gData.FIELDS
                        ),
                        gIndex == groupsOrdered.length - 1 && this.props.footer ? this.props.footer : null
                    ));
                }
            }).bind(this));
            if (this.props.additionalPanes) {
                var otherPanes = { top: [], bottom: [] };
                var depth = this.props.depth;
                var index = 0;
                for (var k in otherPanes) {
                    if (!otherPanes.hasOwnProperty(k)) continue;
                    if (this.props.additionalPanes[k]) {
                        this.props.additionalPanes[k].map(function (p) {
                            if (depth == 0) {
                                otherPanes[k].push(React.createElement(
                                    ReactMUI.Paper,
                                    { className: 'pydio-form-group additional', key: 'other-pane-' + index },
                                    p
                                ));
                            } else {
                                otherPanes[k].push(React.createElement(
                                    'div',
                                    { className: 'pydio-form-group additional', key: 'other-pane-' + index },
                                    p
                                ));
                            }
                            index++;
                        });
                    }
                }
                groupPanes = otherPanes['top'].concat(groupPanes).concat(otherPanes['bottom']);
            }

            if (this.props.tabs) {
                var className = this.props.className;
                var tabs = this.props.tabs.map(function (tDef) {
                    var label = tDef['label'];
                    var groups = tDef['groups'];
                    var panes = groups.map(function (gId) {
                        if (groupPanes[gId]) {
                            return groupPanes[gId];
                        } else {
                            return null;
                        }
                    });
                    return React.createElement(
                        ReactMUI.Tab,
                        { label: label, key: label },
                        React.createElement(
                            'div',
                            { className: (className ? className + ' ' : ' ') + 'pydio-form-panel' + (panes.length % 2 ? ' form-panel-odd' : '') },
                            panes
                        )
                    );
                });
                return React.createElement(
                    'div',
                    { className: 'layout-fill vertical-layout tab-vertical-layout' },
                    React.createElement(
                        ReactMUI.Tabs,
                        null,
                        tabs
                    )
                );
            } else {
                return React.createElement(
                    'div',
                    { className: (this.props.className ? this.props.className + ' ' : ' ') + 'pydio-form-panel' + (groupPanes.length % 2 ? ' form-panel-odd' : ''), onScroll: this.props.onScrollCallback },
                    groupPanes
                );
            }
        }

    });

    /**
     * Utility class to parse / handle pydio standard form definitions/values.
     */

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

        PydioFormManager.hasHelper = function hasHelper(pluginId, paramName) {

            var helpers = PydioFormManager.getHelpersCache();
            return helpers[pluginId] && helpers[pluginId]['parameters'][paramName];
        };

        PydioFormManager.getHelpersCache = function getHelpersCache() {
            if (!PydioFormManager.HELPERS_CACHE) {
                var helperCache = {};
                var helpers = XMLUtils.XPathSelectNodes(global.pydio.Registry.getXML(), 'plugins/*/client_settings/resources/js[@type="helper"]');
                for (var i = 0; i < helpers.length; i++) {
                    var helperNode = helpers[i];
                    var plugin = helperNode.getAttribute("plugin");
                    helperCache[plugin] = { namespace: helperNode.getAttribute('className'), parameters: {} };
                    var paramNodes = XMLUtils.XPathSelectNodes(helperNode, 'parameter');
                    for (var k = 0; k < paramNodes.length; k++) {
                        var paramNode = paramNodes[k];
                        helperCache[plugin]['parameters'][paramNode.getAttribute('name')] = true;
                    }
                }
                PydioFormManager.HELPERS_CACHE = helperCache;
            }
            return PydioFormManager.HELPERS_CACHE;
        };

        PydioFormManager.parseParameters = function parseParameters(xmlDocument, query) {
            return XMLUtils.XPathSelectNodes(xmlDocument, query).map((function (node) {
                return PydioFormManager.parameterNodeToHash(node);
            }).bind(this));
        };

        PydioFormManager.parameterNodeToHash = function parameterNodeToHash(paramNode) {
            var paramsAtts = paramNode.attributes;
            var paramsObject = {};
            var collectCdata = false;
            for (var i = 0; i < paramsAtts.length; i++) {
                var attName = paramsAtts.item(i).nodeName;
                var value = paramsAtts.item(i).value;
                if ((attName == "label" || attName == "description" || attName == "group" || attName.indexOf("group_switch_") === 0) && MessageHash[value]) {
                    value = MessageHash[value];
                }
                if (attName == "cdatavalue") {
                    collectCdata = true;
                    continue;
                }
                paramsObject[attName] = value;
            }
            if (collectCdata) {
                paramsObject['value'] = paramNode.firstChild.value;
            }
            if (paramsObject['type'] == 'boolean') {
                if (paramsObject['value'] !== undefined) paramsObject['value'] = paramsObject['value'] == "true";
                if (paramsObject['default'] !== undefined) paramsObject['default'] = paramsObject['default'] == "true";
            } else if (paramsObject['type'] == 'integer') {
                if (paramsObject['value'] !== undefined) paramsObject['value'] = parseInt(paramsObject['value']);
                if (paramsObject['default'] !== undefined) paramsObject['default'] = parseInt(paramsObject['default']);
            }
            return paramsObject;
        };

        PydioFormManager.createFormelement = function createFormelement(props) {
            var value;
            switch (props.attributes['type']) {
                case 'boolean':
                    value = React.createElement(InputBoolean, props);
                    break;
                case 'string':
                case 'textarea':
                case 'password':
                    value = React.createElement(InputText, props);
                    break;
                case 'valid-password':
                    value = React.createElement(ValidPassword, props);
                    break;
                case 'integer':
                    value = React.createElement(InputInteger, props);
                    break;
                case 'button':
                    value = React.createElement(InputButton, props);
                    break;
                case 'monitor':
                    value = React.createElement(MonitoringLabel, props);
                    break;
                case 'image':
                    value = React.createElement(InputImage, props);
                    break;
                case 'select':
                    value = React.createElement(InputSelectBox, props);
                    break;
                case 'legend':
                    value = null;
                    break;
                case 'hidden':
                    value = null;
                    break;
                default:
                    if (!props.value) {
                        value = React.createElement(
                            'span',
                            { className: 'paramValue-empty' },
                            'Empty'
                        );
                    } else {
                        value = props.value;
                    }
                    break;
            }
            return value;
        };

        /**
         *
         * Extract POST-ready values from a combo parameters/values
         *
         * @param definitions Array Standard Form Definition array
         * @param values Object Key/Values of the current form
         * @param prefix String Optional prefix to add to all parameters (by default DRIVER_OPTION_).
         * @returns Object Object with all pydio-compatible POST parameters
         */

        PydioFormManager.getValuesForPOST = function getValuesForPOST(definitions, values) {
            var prefix = arguments.length <= 2 || arguments[2] === undefined ? 'DRIVER_OPTION_' : arguments[2];
            var additionalMetadata = arguments.length <= 3 || arguments[3] === undefined ? null : arguments[3];

            var clientParams = {};
            for (var key in values) {
                if (values.hasOwnProperty(key)) {
                    clientParams[prefix + key] = values[key];
                    var defType = null;
                    for (var d = 0; d < definitions.length; d++) {
                        if (definitions[d]['name'] == key) {
                            defType = definitions[d]['type'];
                            break;
                        }
                    }
                    if (!defType) {

                        var parts = key.split('/');
                        var last, prev;
                        if (parts.length > 1) {
                            last = parts.pop();
                            prev = parts.pop();
                        }
                        for (var k = 0; k < definitions.length; k++) {
                            if (last !== undefined) {
                                if (definitions[k]['name'] == last && definitions[k]['group_switch_name'] && definitions[k]['group_switch_name'] == prev) {
                                    defType = definitions[k]['type'];
                                    break;
                                }
                            } else {
                                if (definitions[k]['name'] == key) {
                                    defType = definitions[k]['type'];
                                    break;
                                }
                            }
                        }
                    }
                    //definitions.map(function(d){if(d.name == theKey) defType = d.type});
                    if (defType) {
                        if (defType == "image") defType = "binary";
                        clientParams[prefix + key + '_ajxptype'] = defType;
                    }
                    if (additionalMetadata && additionalMetadata[key]) {
                        for (var meta in additionalMetadata[key]) {
                            if (additionalMetadata[key].hasOwnProperty(meta)) {
                                clientParams[prefix + key + '_' + meta] = additionalMetadata[key][meta];
                            }
                        }
                    }
                }
            }

            // Reorder tree keys
            var allKeys = Object.keys(clientParams);
            allKeys.sort();
            allKeys.reverse();
            var treeKeys = {};
            allKeys.each(function (key) {
                if (key.indexOf("/") === -1) return;
                if (key.endsWith("_ajxptype")) return;
                var typeKey = key + "_ajxptype";
                var parts = key.split("/");
                var parentName = parts.shift();
                var parentKey;
                while (parts.length > 0) {
                    if (!parentKey) {
                        parentKey = treeKeys;
                    }
                    if (!parentKey[parentName]) {
                        parentKey[parentName] = {};
                    }
                    parentKey = parentKey[parentName];
                    parentName = parts.shift();
                }
                var type = clientParams[typeKey];
                delete clientParams[typeKey];
                if (parentKey && !parentKey[parentName]) {
                    if (type == "boolean") {
                        var v = clientParams[key];
                        parentKey[parentName] = v == "true" || v == 1 || v === true;
                    } else if (type == "integer") {
                        parentKey[parentName] = parseInt(clientParams[key]);
                    } else if (type && type.startsWith("group_switch:") && typeof clientParams[key] == "string") {
                        parentKey[parentName] = { group_switch_value: clientParams[key] };
                    } else {
                        parentKey[parentName] = clientParams[key];
                    }
                } else if (parentKey && type && type.startsWith('group_switch:')) {
                    parentKey[parentName]["group_switch_value"] = clientParams[key];
                }
                delete clientParams[key];
            });
            for (key in treeKeys) {
                if (!treeKeys.hasOwnProperty(key)) continue;
                var treeValue = treeKeys[key];
                if (clientParams[key + '_ajxptype'] && clientParams[key + '_ajxptype'].indexOf('group_switch:') === 0 && !treeValue['group_switch_value']) {
                    treeValue['group_switch_value'] = clientParams[key];
                }

                clientParams[key] = JSON.stringify(treeValue);
                clientParams[key + '_ajxptype'] = "text/json";
            }

            // Clean XXX_group_switch parameters
            for (var theKey in clientParams) {
                if (!clientParams.hasOwnProperty(theKey)) continue;

                if (theKey.indexOf("/") == -1 && clientParams[theKey] && clientParams[theKey + "_ajxptype"] && clientParams[theKey + "_ajxptype"].startsWith("group_switch:")) {
                    if (typeof clientParams[theKey] == "string") {
                        clientParams[theKey] = JSON.stringify({ group_switch_value: clientParams[theKey] });
                        clientParams[theKey + "_ajxptype"] = "text/json";
                    }
                }
                if (clientParams.hasOwnProperty(theKey)) {
                    if (theKey.endsWith("_group_switch")) {
                        delete clientParams[theKey];
                    }
                }
            }

            return clientParams;
        };

        return PydioFormManager;
    })();

    var PydioForm = global.PydioForm || {};

    PydioForm.createFormElement = PydioFormManager.createFormelement;
    PydioForm.Manager = PydioFormManager;
    PydioForm.InputText = InputText;
    PydioForm.ValidPassword = ValidPassword;
    PydioForm.InputBoolean = InputBoolean;
    PydioForm.InputInteger = InputInteger;
    PydioForm.InputButton = InputButton;
    PydioForm.MonitoringLabel = MonitoringLabel;
    PydioForm.InputSelectBox = InputSelectBox;
    PydioForm.InputImage = InputImage;
    PydioForm.FormPanel = PydioFormPanel;
    PydioForm.PydioHelper = PydioFormHelper;
    PydioForm.HelperMixin = HelperMixin;

    global.PydioForm = PydioForm;
})(window);
