"use strict";
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
    if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
    return cooked;
};
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var assign = require("lodash/assign");
var cloneDeep = require("lodash/cloneDeep");
var find = require("lodash/find");
var first = require("lodash/first");
var get = require("lodash/get");
var set = require("lodash/set");
var moment = require("moment");
var React = require("react");
var fa_1 = require("react-icons/lib/fa");
var styled_components_1 = require("styled-components");
var theme_1 = require("../../theme");
var utils = require("../../utils");
var Button_1 = require("../Button");
var DeleteButton_1 = require("../DeleteButton");
var Grid_1 = require("../Grid");
var Modal_1 = require("../Modal");
var Text_1 = require("../Text");
var FilterForm_1 = require("./FilterForm");
var SchemaSieve_1 = require("./SchemaSieve");
var Summary_1 = require("./Summary");
var ViewsMenu_1 = require("./ViewsMenu");
var sieve = SchemaSieve_1.default();
var RelativeBox = styled_components_1.default(Grid_1.Box)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n\tposition: relative;\n"], ["\n\tposition: relative;\n"])));
var ExtraRuleDeleteBtn = styled_components_1.default(DeleteButton_1.default)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n\tposition: absolute;\n\tbottom: 7px;\n\tright: -35px;\n"], ["\n\tposition: absolute;\n\tbottom: 7px;\n\tright: -35px;\n"])));
var SimpleSearchBox = styled_components_1.default.div(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n\tposition: relative;\n\twidth: 500px;\n\tborder-bottom: 2px solid ", ";\n\tpadding-left: 20px;\n\tpadding-top: 3px;\n\tmargin-left: 30px;\n\tmargin-right: 30px;\n\n\t.search-icon {\n\t\tposition: absolute;\n\t\ttop: 7px;\n\t\tleft: 0;\n\t\tcolor: ", ";\n\t}\n\n\tinput {\n\t\tbackground: transparent;\n\t\tbox-shadow: none;\n\t\tborder: none;\n\t\twidth: 100%;\n\t\tfont-size: inherit;\n\t\tpadding: 5px;\n\t\t::placeholder {\n\t\t\tfont-style: italic;\n\t\t\tcolor: ", ";\n\t\t}\n\t}\n"], ["\n\tposition: relative;\n\twidth: 500px;\n\tborder-bottom: 2px solid ", ";\n\tpadding-left: 20px;\n\tpadding-top: 3px;\n\tmargin-left: 30px;\n\tmargin-right: 30px;\n\n\t.search-icon {\n\t\tposition: absolute;\n\t\ttop: 7px;\n\t\tleft: 0;\n\t\tcolor: ", ";\n\t}\n\n\tinput {\n\t\tbackground: transparent;\n\t\tbox-shadow: none;\n\t\tborder: none;\n\t\twidth: 100%;\n\t\tfont-size: inherit;\n\t\tpadding: 5px;\n\t\t::placeholder {\n\t\t\tfont-style: italic;\n\t\t\tcolor: ", ";\n\t\t}\n\t}\n"])), theme_1.default.colors.gray.main, theme_1.default.colors.gray.main, theme_1.default.colors.gray.main);
var FilterWrapper = styled_components_1.default(Grid_1.Box)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n\tposition: relative;\n"], ["\n\tposition: relative;\n"])));
var Filters = (function (_super) {
    __extends(Filters, _super);
    function Filters(props) {
        var _this = _super.call(this, props) || this;
        _this.handleFilterFormChange = _this.handleFilterFormChange.bind(_this);
        _this.handleExtraFilterFormChange = _this.handleExtraFilterFormChange.bind(_this);
        _this.generateFreshEdit = _this.generateFreshEdit.bind(_this);
        var rules = _this.props.rules;
        var existingRule = find(rules, { name: sieve.SIMPLE_SEARCH_NAME });
        _this.state = {
            showModal: false,
            edit: _this.generateFreshEdit(),
            searchString: (existingRule && existingRule.value) || '',
        };
        _this.filterAndSetRules(rules);
        return _this;
    }
    Filters.prototype.componentWillReceiveProps = function (nextProps) {
        var currentRules = nextProps.rules;
        var existing = find(currentRules, { name: sieve.SIMPLE_SEARCH_NAME });
        if (existing) {
            var value = existing.value;
            if (value !== this.state.searchString) {
                this.setState({ searchString: value });
            }
        }
        else {
            this.setState({ searchString: '' });
        }
    };
    Filters.prototype.filterInvalidRules = function (rules) {
        var _this = this;
        return rules.filter(function (rule) {
            return (rule.name === sieve.SIMPLE_SEARCH_NAME && rule.value) ||
                _this.props.schema.hasOwnProperty(rule.name);
        });
    };
    Filters.prototype.filterAndSetRules = function (rules) {
        this.props.setRules(this.filterInvalidRules(rules));
    };
    Filters.prototype.generateFreshEdit = function () {
        if (!this.props.schema) {
            return {};
        }
        var inputModels = sieve.makeFilterInputs(this.props.schema);
        var edit = {
            name: Object.keys(inputModels).shift(),
            value: '',
        };
        edit.operator = inputModels[edit.name].availableOperators[0].value;
        edit.label = inputModels[edit.name].label;
        edit.type = inputModels[edit.name].type;
        return this.getDefaultEditData(edit, edit.name);
    };
    Filters.prototype.addFilterRule = function (rule) {
        var rules = this.props.rules;
        rules.push(rule);
        this.filterAndSetRules(rules);
    };
    Filters.prototype.editFilterRule = function (rule) {
        var rules = this.props.rules;
        var updatedRules = rules.map(function (r) { return (r.id === rule.id ? rule : r); });
        this.filterAndSetRules(updatedRules);
    };
    Filters.prototype.addRule = function () {
        var inputModels = sieve.makeFilterInputs(this.props.schema);
        var rule = cloneDeep(this.state.edit);
        var baseRule = inputModels[rule.name];
        var newRule = assign(cloneDeep(baseRule), rule);
        if (newRule.id) {
            this.editFilterRule(newRule);
        }
        else {
            newRule.id = utils.randomString();
            this.addFilterRule(newRule);
        }
        this.setState({
            showModal: false,
            edit: this.generateFreshEdit(),
        });
    };
    Filters.prototype.updateSimpleSearch = function (val) {
        this.setState({ searchString: val });
        var rules = this.props.rules;
        var existingRule = find(rules, { name: sieve.SIMPLE_SEARCH_NAME });
        if (existingRule) {
            existingRule.value = val;
            this.editFilterRule(existingRule);
        }
        else {
            this.addFilterRule({
                name: sieve.SIMPLE_SEARCH_NAME,
                value: val,
                id: utils.randomString(),
            });
        }
    };
    Filters.prototype.showEditModal = function (rule) {
        this.setState({
            showModal: true,
            edit: cloneDeep(rule),
        });
    };
    Filters.prototype.removeRule = function (rule) {
        if (rule.name === sieve.SIMPLE_SEARCH_NAME) {
            this.setState({ searchString: '' });
        }
        var rules = this.props.rules;
        var updatedRules = rules.filter(function (r) { return r.id !== rule.id; });
        this.filterAndSetRules(updatedRules);
    };
    Filters.prototype.getDefaultEditData = function (data, value) {
        var update = cloneDeep(data);
        var inputModels = sieve.makeFilterInputs(this.props.schema);
        var model = inputModels[value];
        update.type = model.type;
        update.name = value;
        update.operator = model.availableOperators[0].value;
        update.label = model.label;
        if (model.type === 'Date Time') {
            update.value = moment().format('YYYY-MM-DDTHH:mm');
        }
        else if (model.type === 'Date') {
            update.value = moment().format('YYYY-MM-DD');
        }
        else if (model.type === 'Time') {
            update.value = moment().format('HH:mm');
        }
        else if (model.type === 'Enum') {
            update.value = first(this.props.schema[model.name].values);
        }
        else {
            update.value = '';
        }
        return update;
    };
    Filters.prototype.updateFilter = function (filterBase, attribute, value) {
        var filter = __assign({}, filterBase);
        if (attribute === 'name' && filter.name !== value) {
            filter = this.getDefaultEditData(filter, value);
        }
        else if (attribute === 'operator') {
            filter.value = '';
            filter[attribute] = value;
        }
        else {
            set(filter, attribute, value);
        }
        return filter;
    };
    Filters.prototype.handleFilterFormChange = function (value, attribute) {
        var update = this.updateFilter(this.state.edit, attribute, value);
        this.setState({ edit: update });
    };
    Filters.prototype.handleExtraFilterFormChange = function (index, value, attribute) {
        var extra = this.state.edit.extra || { or: [] };
        var filter = get(extra.or, index);
        if (!filter) {
            return;
        }
        var update = this.updateFilter(filter, attribute, value);
        set(extra.or, index, update);
        this.setState(function (prevState) { return ({ edit: __assign({}, prevState.edit, { extra: extra }) }); });
    };
    Filters.prototype.addExtraRule = function () {
        var extra = this.state.edit.extra || { or: [] };
        extra.or.push(this.generateFreshEdit());
        this.setState(function (prevState) { return ({ edit: __assign({}, prevState.edit, { extra: extra }) }); });
    };
    Filters.prototype.removeExtraRule = function (index) {
        var extra = this.state.edit.extra || { or: [] };
        extra.or.splice(index, 1);
        this.setState(function (prevState) { return ({ edit: __assign({}, prevState.edit, { extra: extra }) }); });
    };
    Filters.prototype.saveView = function (name, scopeKey) {
        var rules = this.props.rules;
        var views = this.props.views;
        var newView = {
            name: name,
            rules: cloneDeep(rules),
            id: utils.randomString(),
            scopeKey: scopeKey,
        };
        if (!views) {
            views = [];
        }
        var store = find(views, function (item) { return item.key === scopeKey; });
        if (store) {
            store.data.push(newView);
            this.props.setViews(views);
        }
    };
    Filters.prototype.deleteView = function (view, scopeKey) {
        var views = this.props.views;
        var store = find(views, function (item) { return item.key === scopeKey; });
        if (store) {
            store.data = store.data.filter(function (v) { return v.id !== view.id; });
            this.props.setViews(views);
        }
    };
    Filters.prototype.showNewFilterModal = function () {
        this.setState({
            showModal: true,
            edit: this.generateFreshEdit(),
        });
    };
    Filters.prototype.render = function () {
        var _this = this;
        var inputModels = sieve.makeFilterInputs(this.props.schema);
        var rules = this.props.rules || [];
        return (React.createElement(FilterWrapper, { mb: 3 },
            React.createElement(Grid_1.Flex, { justify: "space-between" },
                React.createElement(Button_1.default, __assign({ disabled: this.props.disabled, primary: true, onClick: function () { return _this.showNewFilterModal(); } }, this.props.addFilterButtonProps),
                    React.createElement(fa_1.FaFilter, { style: { marginRight: 10 } }),
                    "Add filter"),
                React.createElement(SimpleSearchBox, null,
                    React.createElement("input", { style: { color: this.props.dark ? '#fff' : null }, disabled: this.props.disabled, placeholder: "Search entries...", value: this.state.searchString, onChange: function (e) { return _this.updateSimpleSearch(e.target.value); } }),
                    React.createElement(fa_1.FaSearch, { className: "search-icon", name: "search" })),
                React.createElement(ViewsMenu_1.default, { buttonProps: this.props.viewsMenuButtonProps, disabled: this.props.disabled, rules: rules, views: this.props.views || [], schema: this.props.schema, setRules: function (rules) { return _this.filterAndSetRules(rules); }, deleteView: function (view, scopeKey) { return _this.deleteView(view, scopeKey); } })),
            this.state.showModal && (React.createElement("div", null,
                React.createElement(Modal_1.default, { title: "Filter by", cancel: function () { return _this.setState({ showModal: false }); }, done: function () { return _this.addRule(); }, action: "Save" },
                    React.createElement("form", { onSubmit: function (e) { return e.preventDefault() || _this.addRule(); } },
                        React.createElement(FilterForm_1.default, { handleEditChange: this.handleFilterFormChange, inputModels: inputModels, name: this.state.edit.name, value: this.state.edit.value, operator: this.state.edit.operator, schema: this.props.schema }),
                        !!this.state.edit.extra &&
                            this.state.edit.extra.or.map(function (rule, index) { return (React.createElement(RelativeBox, { key: index },
                                React.createElement(Text_1.default, { my: 2 }, "OR"),
                                React.createElement(FilterForm_1.default, { handleEditChange: function (value, key) {
                                        return _this.handleExtraFilterFormChange(index, value, key);
                                    }, inputModels: inputModels, name: rule.name, value: rule.value, operator: rule.operator, schema: _this.props.schema }),
                                React.createElement(ExtraRuleDeleteBtn, { onClick: function () { return _this.removeExtraRule(index); } }))); }),
                        React.createElement(Button_1.default, { mb: 2, mt: 4, primary: true, underline: true, onClick: function () { return _this.addExtraRule(); } }, "Add alternative"))))),
            !!rules.length &&
                !this.props.disabled && (React.createElement(Summary_1.default, { edit: function (rule) { return _this.showEditModal(rule); }, delete: function (rule) { return _this.removeRule(rule); }, saveView: function (name, scope) { return _this.saveView(name, scope); }, rules: rules, views: this.props.views || [], schema: this.props.schema, dark: !!this.props.dark }))));
    };
    return Filters;
}(React.Component));
exports.default = Filters;
var templateObject_1, templateObject_2, templateObject_3, templateObject_4;
