"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 React = require("react");
var moment = require("moment");
var cloneDeep = require("lodash/cloneDeep");
var first = require("lodash/first");
var find = require("lodash/find");
var assign = require("lodash/assign");
var map = require("lodash/map");
var FaFilter = require("react-icons/lib/fa/filter");
var FaSearch = require("react-icons/lib/fa/search");
var styled_components_1 = require("styled-components");
var Summary_1 = require("./Summary");
var ViewsMenu_1 = require("./ViewsMenu");
var Button_1 = require("../Button");
var Modal_1 = require("../Modal");
var Select_1 = require("../Select");
var Grid_1 = require("../Grid");
var utils = require("../../utils");
var SchemaSieve_1 = require("./SchemaSieve");
var PineTypes_1 = require("../PineTypes");
var theme_1 = require("../../theme");
var sieve = SchemaSieve_1.default();
var SimpleSearchBox = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n  position: relative;\n  width: 500px;\n  border-bottom: 2px solid ", ";\n  padding-left: 20px;\n  padding-top: 3px;\n  margin-left: 30px;\n  margin-right: 30px;\n\n  .search-icon {\n    position: absolute;\n    top: 7px;\n    left: 0;\n    color: ", ";\n  }\n\n  input {\n    background: transparent;\n    box-shadow: none;\n    border: none;\n    width: 100%;\n    font-size: inherit;\n    padding: 5px;\n    ::placeholder {\n      font-style: italic;\n      color: ", ";\n    }\n  }\n"], ["\n  position: relative;\n  width: 500px;\n  border-bottom: 2px solid ", ";\n  padding-left: 20px;\n  padding-top: 3px;\n  margin-left: 30px;\n  margin-right: 30px;\n\n  .search-icon {\n    position: absolute;\n    top: 7px;\n    left: 0;\n    color: ", ";\n  }\n\n  input {\n    background: transparent;\n    box-shadow: none;\n    border: none;\n    width: 100%;\n    font-size: inherit;\n    padding: 5px;\n    ::placeholder {\n      font-style: italic;\n      color: ", ";\n    }\n  }\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_2 || (templateObject_2 = __makeTemplateObject(["\n  position: relative;\n"], ["\n  position: relative;\n"])));
var FilterInput = function (props) {
    var PineTypeInput = PineTypes_1.default[props.type].Edit;
    return (React.createElement(PineTypeInput, { schema: props.schema, value: props.value, operator: props.operator, onChange: props.onChange }));
};
var Filters = (function (_super) {
    __extends(Filters, _super);
    function Filters(props) {
        var _this = _super.call(this, props) || this;
        _this.handleEditChange = _this.handleEditChange.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.setDefaultEditData(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 (rule) {
        var inputModels = sieve.makeFilterInputs(this.props.schema);
        if (!rule) {
            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.setDefaultEditData = 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.handleEditChange = function (value, attribute) {
        var update = this.state.edit;
        if (attribute === 'name' && update.name !== value) {
            update = this.setDefaultEditData(update, value);
        }
        else if (attribute === 'operator') {
            update.value = null;
            update[attribute] = value;
        }
        else {
            update[attribute] = value;
        }
        this.setState({ edit: update });
    };
    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 = views.find(function (item) { return item.key === scopeKey; });
        store.data.push(newView);
        this.props.setViews(views);
    };
    Filters.prototype.deleteView = function (view, scopeKey) {
        var views = this.props.views;
        var store = views.find(function (item) { return item.key === scopeKey; });
        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(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(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: this.state.edit.id ? 'Update filter' : 'Add filter' },
                    React.createElement("form", { onSubmit: function (e) { return e.preventDefault() || _this.addRule(); } },
                        React.createElement(Grid_1.Flex, null,
                            React.createElement(Select_1.default, { mr: 20, value: this.state.edit.name, onChange: function (e) {
                                    return _this.handleEditChange(e.target.value, 'name');
                                } }, map(inputModels, function (_a) {
                                var name = _a.name, label = _a.label;
                                return (React.createElement("option", { key: name, value: name }, label || name));
                            })),
                            React.createElement(Select_1.default, { mr: 20, value: this.state.edit.operator, onChange: function (e) {
                                    return _this.handleEditChange(e.target.value, 'operator');
                                } }, map(inputModels[this.state.edit.name].availableOperators, function (_a) {
                                var value = _a.value, label = _a.label;
                                return (React.createElement("option", { value: value, key: value }, label));
                            })),
                            inputModels[this.state.edit.name].type !== 'Boolean' && (React.createElement(FilterInput, { operator: this.state.edit.operator, schema: this.props.schema[this.state.edit.name], value: this.state.edit.value, onChange: function (value) { return _this.handleEditChange(value, 'value'); }, type: inputModels[this.state.edit.name].type, autoFocus: true }))))))),
            !!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;
