import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { ServerSideFieldModel } from '../../services/ServerSideFieldModel';
import { I18nService } from '../../services/system/locale/I18n';
import { ObservableHack } from '../../services/util/ObservableHack';
import { Verify } from '../../services/validation/Verify';
import { LoggerService } from 'dotcms-js/dotcms-js';
var ServersideCondition = (function () {
    function ServersideCondition(fb, resources, loggerService) {
        this.loggerService = loggerService;
        this.parameterValueChange = new EventEmitter(false);
        this._errorMessageFormatters = {
            minLength: 'Input must be at least ${len} characters long.',
            noQuotes: 'Input cannot contain quote [" or \'] characters.',
            required: 'Required'
        };
        this._resources = resources;
        this._inputs = [];
    }
    ServersideCondition.getRightHandArgCount = function (selectedComparison) {
        var argCount = null;
        if (selectedComparison) {
            argCount = Verify.isNumber(selectedComparison.rightHandArgCount)
                ? selectedComparison.rightHandArgCount
                : 1;
        }
        return argCount;
    };
    ServersideCondition.isComparisonParameter = function (input) {
        return input && input.name === 'comparison';
    };
    // tslint:disable-next-line:no-unused-variable
    ServersideCondition.getSelectedOption = function (input, value) {
        var opt = null;
        var optAry = input.options.filter(function (e) { return e.value === value; });
        if (optAry && optAry.length === 1) {
            opt = optAry[0];
        }
        return opt;
    };
    ServersideCondition.prototype.ngOnChanges = function (change) {
        var _this = this;
        var paramDefs = null;
        if (change.componentInstance) {
            this._rhArgCount = null;
            paramDefs = this.componentInstance.type.parameters;
        }
        if (paramDefs) {
            var prevPriority_1 = 0;
            this._inputs = [];
            Object.keys(paramDefs).forEach(function (key) {
                var paramDef = _this.componentInstance.getParameterDef(key);
                var param = _this.componentInstance.getParameter(key);
                if (paramDef.priority > prevPriority_1 + 1) {
                    _this._inputs.push({ flex: 40, type: 'spacer' });
                }
                prevPriority_1 = paramDef.priority;
                _this.loggerService.info('ServersideCondition', 'onChange', 'params', key, param);
                var input = _this.getInputFor(paramDef.inputType.type, param, paramDef);
                _this._inputs.push(input);
            });
            var comparison_1;
            var comparisonIdx_1 = null;
            this._inputs.forEach(function (input, idx) {
                if (ServersideCondition.isComparisonParameter(input)) {
                    comparison_1 = input;
                    _this.applyRhsCount(comparison_1.value);
                    comparisonIdx_1 = idx;
                }
                else if (comparisonIdx_1 !== null) {
                    if (_this._rhArgCount !== null) {
                        input.argIndex = idx - comparisonIdx_1 - 1;
                    }
                }
            });
            if (comparison_1) {
                this.applyRhsCount(comparison_1.value);
            }
        }
    };
    /**
   * Brute force error messages from lookup table for now.
   * @todo look up the known error formatters by key ('required', 'minLength', etc) from the I18NResource endpoint
   * and pre-cache them, so that we can retrieve them synchronously.
   */
    ServersideCondition.prototype.getErrorMessage = function (input) {
        var _this = this;
        var control = input.control;
        var message = '';
        Object.keys(control.errors || {}).forEach(function (key) {
            var err = control.errors[key];
            message += _this._errorMessageFormatters[key];
            if (Object.keys(err).length) {
                // tslint:disable-next-line:no-debugger
                debugger;
            }
        });
        return message;
    };
    ServersideCondition.prototype.onBlur = function (input) {
        if (input.control.dirty) {
            this.setParameterValue(input.name, input.control.value, input.control.valid, true);
        }
    };
    ServersideCondition.prototype.setParameterValue = function (name, value, valid, isBlur) {
        if (isBlur === void 0) { isBlur = false; }
        this.parameterValueChange.emit({ name: name, value: value });
        if (name === 'comparison') {
            this.applyRhsCount(value);
        }
    };
    ServersideCondition.prototype.getInputFor = function (type, param, paramDef) {
        var i18nBaseKey = paramDef.i18nBaseKey || this.componentInstance.type.i18nKey;
        /* Save a potentially large number of requests by loading parent key: */
        this._resources.get(i18nBaseKey).subscribe(function () { });
        var input;
        if (type === 'text' || type === 'number') {
            input = this.getTextInput(param, paramDef, i18nBaseKey);
            this.loggerService.info('ServersideCondition', 'getInputFor', type, paramDef);
        }
        else if (type === 'datetime') {
            input = this.getDateTimeInput(param, paramDef, i18nBaseKey);
        }
        else if (type === 'restDropdown') {
            input = this.getRestDropdownInput(param, paramDef, i18nBaseKey);
        }
        else if (type === 'dropdown') {
            input = this.getDropdownInput(param, paramDef, i18nBaseKey);
        }
        input.type = type;
        return input;
    };
    ServersideCondition.prototype.getTextInput = function (param, paramDef, i18nBaseKey) {
        var rsrcKey = i18nBaseKey + '.inputs.' + paramDef.key;
        var placeholderKey = rsrcKey + '.placeholder';
        var control = ServerSideFieldModel.createNgControl(this.componentInstance, param.key);
        return {
            control: control,
            name: param.key,
            placeholder: this._resources.get(placeholderKey, paramDef.key),
            required: paramDef.inputType.dataType['minLength'] > 0
        };
    };
    ServersideCondition.prototype.getDateTimeInput = function (param, paramDef, i18nBaseKey) {
        // tslint:disable-next-line:no-unused-variable
        var rsrcKey = i18nBaseKey + '.inputs.' + paramDef.key;
        return {
            control: ServerSideFieldModel.createNgControl(this.componentInstance, param.key),
            name: param.key,
            required: paramDef.inputType.dataType['minLength'] > 0,
            value: this.componentInstance.getParameterValue(param.key),
            visible: true
        };
    };
    ServersideCondition.prototype.getRestDropdownInput = function (param, paramDef, i18nBaseKey) {
        var inputType = paramDef.inputType;
        var rsrcKey = i18nBaseKey + '.inputs.' + paramDef.key;
        var placeholderKey = rsrcKey + '.placeholder';
        var currentValue = this.componentInstance.getParameterValue(param.key);
        if (currentValue &&
            (currentValue.indexOf('"') !== -1 || currentValue.indexOf('\'') !== -1)) {
            currentValue = currentValue.replace(/["']/g, '');
            this.componentInstance.setParameter(param.key, currentValue);
        }
        var control = ServerSideFieldModel.createNgControl(this.componentInstance, param.key);
        var input = {
            allowAdditions: inputType.allowAdditions,
            control: control,
            maxSelections: inputType.maxSelections,
            minSelections: inputType.minSelections,
            name: param.key,
            optionLabelField: inputType.optionLabelField,
            optionUrl: inputType.optionUrl,
            optionValueField: inputType.optionValueField,
            placeholder: this._resources.get(placeholderKey, paramDef.key),
            required: inputType.minSelections > 0,
            value: currentValue
        };
        if (!input.value) {
            input.value = inputType.selected != null ? inputType.selected : '';
        }
        return input;
    };
    ServersideCondition.prototype.getDropdownInput = function (param, paramDef, i18nBaseKey) {
        var _this = this;
        var inputType = paramDef.inputType;
        var opts = [];
        var options = inputType.options;
        var rsrcKey = i18nBaseKey + '.inputs.' + paramDef.key;
        var placeholderKey = rsrcKey + '.placeholder';
        if (param.key === 'comparison') {
            rsrcKey = 'api.sites.ruleengine.rules.inputs.comparison';
        }
        else {
            rsrcKey = rsrcKey + '.options';
        }
        var currentValue = this.componentInstance.getParameterValue(param.key);
        var needsCustomAttribute = currentValue != null;
        Object.keys(options).forEach(function (key) {
            var option = options[key];
            if (needsCustomAttribute && key === currentValue) {
                needsCustomAttribute = false;
            }
            var labelKey = rsrcKey + '.' + option.i18nKey;
            // hack for country - @todo ggranum: kill 'name' on locale?
            if (param.key === 'country') {
                labelKey = i18nBaseKey + '.' + option.i18nKey + '.name';
            }
            opts.push({
                icon: option.icon,
                label: _this._resources.get(labelKey, option.i18nKey),
                rightHandArgCount: option.rightHandArgCount,
                value: key
            });
        });
        if (needsCustomAttribute) {
            opts.push({
                label: ObservableHack.of(currentValue),
                value: currentValue
            });
        }
        var input = {
            allowAdditions: inputType.allowAdditions,
            control: ServerSideFieldModel.createNgControl(this.componentInstance, param.key),
            maxSelections: inputType.maxSelections,
            minSelections: inputType.minSelections,
            name: param.key,
            options: opts,
            placeholder: this._resources.get(placeholderKey, paramDef.key),
            required: inputType.minSelections > 0,
            value: currentValue
        };
        if (!input.value) {
            input.value = inputType.selected != null ? inputType.selected : '';
        }
        return input;
    };
    ServersideCondition.prototype.applyRhsCount = function (selectedComparison) {
        var comparisonDef = this.componentInstance.getParameterDef('comparison');
        var comparisonType = comparisonDef.inputType;
        var selectedComparisonDef = comparisonType.options[selectedComparison];
        this._rhArgCount = ServersideCondition.getRightHandArgCount(selectedComparisonDef);
    };
    return ServersideCondition;
}());
export { ServersideCondition };
ServersideCondition.decorators = [
    { type: Component, args: [{
                changeDetection: ChangeDetectionStrategy.OnPush,
                selector: 'cw-serverside-condition',
                template: "<form>\n  <div flex layout=\"row\" class=\"cw-condition-component-body\">\n    <ng-template ngFor let-input [ngForOf]=\"_inputs\">\n      <div *ngIf=\"input.type == 'spacer'\" flex class=\"cw-input cw-input-placeholder\">&nbsp;</div>\n      <cw-input-dropdown *ngIf=\"input.type == 'dropdown'\"\n                         flex\n                         class=\"cw-input\"\n                         [hidden]=\"input.argIndex !== null && input.argIndex >= _rhArgCount\"\n                         [formControl]=\"input.control\"\n                         [required]=\"input.required\"\n                         [allowAdditions]=\"input.allowAdditions\"\n                         [class.cw-comparator-selector]=\"input.name == 'comparison'\"\n                         [class.cw-last]=\"islast\"\n                         (touch)=\"onBlur(input)\"\n                         placeholder=\"{{input.placeholder | async}}\">\n        <cw-input-option\n            *ngFor=\"let opt of input.options\"\n            [value]=\"opt.value\"\n            [label]=\"opt.label | async\"\n            icon=\"{{opt.icon}}\"></cw-input-option>\n      </cw-input-dropdown>\n\n      <div flex layout-fill layout=\"column\" class=\"cw-input\" [class.cw-last]=\"islast\" *ngIf=\"input.type == 'restDropdown'\">\n        <cw-input-rest-dropdown flex\n                                class=\"cw-input\"\n                                [value]=\"input.value\"\n                                [formControl]=\"input.control\"\n                                [hidden]=\"input.argIndex !== null && input.argIndex >= _rhArgCount\"\n                                placeholder=\"{{input.placeholder | async}}\"\n                                [minSelections]=\"input.minSelections\"\n                                [maxSelections]=\"input.maxSelections\"\n                                optionUrl=\"{{input.optionUrl}}\"\n                                optionValueField=\"{{input.optionValueField}}\"\n                                optionLabelField=\"{{input.optionLabelField}}\"\n                                [required]=\"input.required\"\n                                [allowAdditions]=\"input.allowAdditions\"\n                                [class.cw-comparator-selector]=\"input.name == 'comparison'\"\n                                [class.cw-last]=\"islast\"\n                                (touch)=\"onBlur(input)\"\n                                #rdInput=\"ngForm\"\n                                >\n        </cw-input-rest-dropdown>\n        <div flex=\"50\" *ngIf=\"rdInput.touched && !rdInput.valid && (input.argIndex == null || input.argIndex < _rhArgCount)\"\n            class=\"name cw-warn basic label\">{{getErrorMessage(input)}}</div>\n      </div>\n\n      <div flex layout-fill layout=\"column\" class=\"cw-input\" [class.cw-last]=\"islast\" *ngIf=\"input.type == 'text' || input.type == 'number'\">\n        <cw-input-text\n            flex\n            [placeholder]=\"input.placeholder | async\"\n            [formControl]=\"input.control\"\n            [type]=\"input.type\"\n            [hidden]=\"input.argIndex !== null && input.argIndex >= _rhArgCount\"\n            (blur)=\"onBlur(input)\"\n            #fInput=\"ngForm\"\n        ></cw-input-text>\n        <div flex=\"50\" *ngIf=\"fInput.touched && !fInput.valid && (input.argIndex == null || input.argIndex < _rhArgCount)\"\n            class=\"name cw-warn basic label\">{{getErrorMessage(input)}}</div>\n      </div>\n\n      <cw-input-date *ngIf=\"input.type == 'datetime'\"\n                     flex\n                    layout-fill\n                     class=\"cw-input\"\n                     [formControl]=\"input.control\"\n                     [class.cw-last]=\"islast\"\n                     [placeholder]=\"input.placeholder | async\"\n                     [hidden]=\"input.argIndex !== null && input.argIndex >= _rhArgCount\"\n                     [value]=\"input.value\"\n                     (blur)=\"onBlur(input)\"\n                     #gInput=\"ngForm\"\n      ></cw-input-date>\n    </ng-template>\n  </div>\n</form>"
            },] },
];
/** @nocollapse */
ServersideCondition.ctorParameters = function () { return [
    { type: FormBuilder, },
    { type: I18nService, },
    { type: LoggerService, },
]; };
ServersideCondition.propDecorators = {
    'componentInstance': [{ type: Input },],
    'parameterValueChange': [{ type: Output },],
};
//# sourceMappingURL=serverside-condition.js.map