<template>
    <div class="tracker-rules">
        <div class="card mb-3">
            <div class="card-header">
                Conditions
            </div>
            <div class="card-body conditions">
                <ui-predicate v-model="conditionsData" :columns="conditionsColumns" @changed="onChangeConditions" @initialized="onChangeConditions"/>
            </div>
        </div>
        <div class="card mb-3">
            <div class="card-header">
                Actions
            </div>
            <div class="card-body actions">
                <ui-predicate v-model="actionsData" :columns="actionsColumns" @changed="onChangeActions" @initialized="onChangeActions"/>
            </div>
        </div>
        <div class="card mb-3">
            <div class="card-header">
                Else
            </div>
            <div class="card-body else">
                <ui-predicate v-model="elseData" :columns="actionsColumns" @changed="onChangeElse" @initialized="onChangeElse"/>
            </div>
        </div>

        <div class="card">
            <div class="card-body tips">
                <h5 class="card-title">Tips</h5>
                <div class="card=text">
                    <p>Tips: Use <code>alt + click</code> to create a sub-group.</p>
                    <p>
                        <button class="btn btn-warning btn-sm" @click="onResetClicked">Clear All</button>
                    </p>
                </div>
            </div>
        </div>

        <div class="card d-none">
            <div class="card-header">
                Conditions Output
            </div>
            <div class="card-content">
                <textarea name="conditions" class="form-control" readonly="readonly">{{ conditionsoutput }}</textarea>
            </div>
        </div>
        <div class="card d-none">
            <div class="card-header">
                Actions Output
            </div>
            <div class="card-content">
                <textarea name="actions" class="form-control" readonly="readonly">{{ actionoutput }}</textarea>
            </div>
        </div>
        <div class="card d-none">
            <div class="card-header">
                Else Output
            </div>
            <div class="card-content">
                <textarea name="else" class="form-control" readonly="readonly">{{ elseoutput }}</textarea>
            </div>
        </div>
    </div>
</template>

<script>
    Vue.use(UIPredicate);

    import TextArgument from "./vue_TextArgument.js";
    import NumberArgument from "./vue_NumberArgument.js";
    import DateArgument from "./vue_DateArgument.js";
    import NoArgument from "./vue_NoArgument.js";
    import BoolArgument from "./vue_BoolArgument.js";
    import CollectionArgument from "./vue_CollectionArgument.js";


    export default {
        name: "tracker-rules",
        components: {},
        data()
        {
            return {
                conditionsoutput: {},
                actionoutput: {},
                elseoutput: {},
                conditionsData: null,
                conditionsColumns: {
                    targets: null,
                    // besides array list names, everything else follows convention
                    // https://github.com/FGRibreau/sql-convention
                    operators: null,
                    types: null,
                    logicalTypes: [
                        {
                            logicalType_id: "any",
                            label: "Any",
                        },
                        {
                            logicalType_id: "all",
                            label: "All",
                        },
                        {
                            logicalType_id: "none",
                            label: "None",
                        },
                    ],
                    argumentTypes: [
                        {
                            argumentType_id: "DateTime",
                            component: DateArgument,
                        },
                        {
                            argumentType_id: "Text",
                            component: TextArgument,
                        },
                        {
                            argumentType_id: "Number",
                            component: NumberArgument,
                        },
                        {
                            argumentType_id: "Boolean",
                            component: BoolArgument,
                        },
                        {
                            argumentType_id: "Nothing",
                            component: NoArgument,
                        },
                        {
                            argumentType_id: "Collection",
                            component: CollectionArgument,
                        },
                    ],
                },
                actionsData: null,
                actionsColumns: {
                    targets: null,
                    operators: null,
                    types: null,
                    // TODO logicalTypes should be removed for actions
                    logicalTypes: [
                        {
                            logicalType_id: "any",
                            label: "Any",
                        },
                        {
                            logicalType_id: "all",
                            label: "All",
                        },
                        {
                            logicalType_id: "none",
                            label: "None",
                        },
                    ],
                    argumentTypes: [
                        {
                            argumentType_id: "Nothing",
                            component: NoArgument,
                        },
                    ],
                },
                elseData: null,
            };
        },
        methods: {

            onChangeConditions(diff)
            {
                this.conditionsoutput = diff;
            },
            onChangeActions(diff)
            {
                this.actionoutput = diff;
            },
            onChangeElse(diff)
            {
                this.elseoutput = diff;
            },
            onResetClicked(event)
            {
                this.conditionsoutput = "";
                this.actionoutput = "";
                this.elseoutput = "";

                $(this.$el).find(".card-body:not(.tips)").empty();

                event.preventDefault();
                return false;
            },
        },
        beforeMount: function () {

            let fields = this.$parent.targetFields,
                field = {},
                thisvue = this,
                conditionsTargets = [],
                actionsTargets = [{
                    target_id: "NoTarget",
                    label: "",
                    type_id: "Nothing",

                }];

            thisvue.conditionsColumns.operators = thisvue.$parent.definitiion.operators;
            thisvue.conditionsColumns.types     = thisvue.$parent.definitiion.types;
            thisvue.actionsColumns.operators    = thisvue.$parent.definitiion.actions;
            thisvue.actionsColumns.types        = thisvue.$parent.definitiion.types;

            if (fields !== undefined) {

                fields.forEach(function (value) {
                    conditionsTargets.push({
                        target_id: value.ins_id,
                        label: value.name,
                        type_id: value.argumentType,
                    });
                    actionsTargets.push({
                        target_id: value.ins_id,
                        label: value.name,
                        type_id: "Field",
                    });

                    if (value.fieldId === thisvue.$parent.fieldId ||
                        value.argumentType === "Collection" && value.fieldId === (thisvue.$parent.fieldId + "[]")) {
                        field = value;
                    }
                });

                thisvue.conditionsColumns.targets = conditionsTargets;
                thisvue.actionsColumns.targets    = actionsTargets;
            }

            // validate the targets in case options have changed or fields deleted
            let getPredicates = function (predicates) {
                return predicates.filter(predicate => {
                    let found = thisvue.actionsColumns.targets.find(target => {
                        if (predicate.target_id === target.target_id) {
                            return true;
                        }
                    });
                    if (! found) {
                        // try for partial matches - can happen if field options change (from or to a collection)
                        found = thisvue.actionsColumns.targets.find(target => {
                            if (predicate.target_id.indexOf(target.target_id) > -1 || target.target_id.indexOf(predicate.target_id) > -1) {
                                return true;
                            }
                        });

                        if (found) {
                            if (predicate.target_id.indexOf("[]") > -1) {
                                predicate.target_id = predicate.target_id.replace("[]", "");
                            } else {
                                predicate.target_id = predicate.target_id + "[]";
                            }
                        } else {
                            console.error("Tracker Field Rules: field " + predicate.target_id + " not found in predicates");
                        }
                    }
                    return found;
                });
            };

            let defaultCondition = function () {
                let operatorId = "";

                if (field.argumentType === "Text") {
                    operatorId = "TextContains";
                } else if (field.argumentType === "Number") {
                    operatorId = "NumberEquals";
                } else if (field.argumentType === "Boolean") {
                    operatorId = "BooleanTrueFalse";
                } else if (field.argumentType === "DateTime") {
                    operatorId = "DateTimeOn";
                } else if (field.argumentType === "Collection") {
                    operatorId = "CollectionContains";
                }

                return {
                    logicalType_id: "any",
                    predicates: [{
                        target_id: "ins_" + field.fieldId,
                        operator_id: operatorId,
                        argument: "",
                    }]
                };
            };

            // set conditions field to this one if nothing else set
            if (! thisvue.$parent.rules.conditions) {
                thisvue.conditionsData = defaultCondition();
            } else {
                thisvue.conditionsData = thisvue.$parent.rules.conditions;
                thisvue.conditionsData.predicates = getPredicates(thisvue.$parent.rules.conditions.predicates);

                if (thisvue.conditionsData.predicates.length === 0) {
                    // we need at least one condition
                    thisvue.conditionsData = defaultCondition();
                }
            }

            if (thisvue.$parent.rules.actions) {
                thisvue.actionsData = thisvue.$parent.rules.actions;
                thisvue.actionsData.predicates = getPredicates(thisvue.$parent.rules.actions.predicates);
            }
            if (thisvue.$parent.rules.else) {
                thisvue.elseData = thisvue.$parent.rules.else;
                thisvue.elseData.predicates = getPredicates(thisvue.$parent.rules.else.predicates);
            }
        }
    };
</script>
