<template>
    <div class="menu-builder" v-cloak>

        <div v-if="is_dirty" class="rounded-sm bg-red-100 p-4 mb-4 border border-red-400">
            <div class="flex">
                <div class="flex-shrink-0">
                    <svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
                        <path fill-rule="evenodd"
                              d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"
                              clip-rule="evenodd"
                        />
                    </svg>
                </div>
                <div class="ml-3">
                    <div class="text-sm leading-5 text-red-800">
                        <p>You have (Unsaved Changes)</p>
                    </div>
                </div>
            </div>
        </div>

        <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
            <div class="col-span-1">
                <menu-builder-form
                    :current-item="currentItem"
                    :mode="mode"
                    :entity-types="entityTypes"
                    @newItem="newItem"
                    @saveItem="saveItem"
                ></menu-builder-form>
            </div>
            <div class="col-span-1 lg:col-span-2">
                <div v-if="items && items.length" :class="['has-items', state]">
                    <draggable :list="items" @update="updateSortOrder">
                        <transition-group name="list" tag="div">
                            <menu-builder-item
                                v-for="(item, index) in orderedItems"
                                v-if="item.parent_id == null"
                                :key="item.id"
                                :index="index"
                                :item="item"
                                :current-item="currentItem"
                                @editItem="editItem"
                                @deleteItem="deleteItem"
                                @editChildItem="editChildItem"
                                @deleteChildItem="deleteChildItem"
                            >
                            </menu-builder-item>
                        </transition-group>
                    </draggable>
                </div>
                <div v-else :class="['no-items', state]">
                    <v-card>
                        <div class="message text-center">
                            <div class="message-text font-semibold">
                                {{ message }}
                            </div>
                        </div>
                    </v-card>
                </div>
            </div>
        </div>
    </div>
</template>


<script>
import MenuBuilderForm from "./MenuBuilderForm";
import MenuBuilderItem from "./MenuBuilderItem";
import Draggable from 'vuedraggable';

export default {
    components : {
        MenuBuilderForm,
        MenuBuilderItem,
        Draggable
    },
    props : {
        menu : {type : Object},
        entityTypes : {type : Array}
    },
    computed : {
        orderedItems : function () {
            return _.orderBy(this.items, this.orderBy)
        }
    },
    data() {
        return {
            items : [],
            currentItem : this.defaultItem(),
            orderBy : 'sort_order',
            message : 'Checking for items, please wait...',
            state : 'loading',
            mode : 'create',
            is_dirty : false,
        }
    },
    methods : {
        generateId() {
            let length = 8,
                timestamp = +new Date,
                ts = timestamp.toString(),
                parts = ts.split("").reverse(),
                id = "";

            let _getRandomInt = function (min, max) {
                return Math.floor(Math.random() * (max - min + 1)) + min;
            };

            for (let i = 0; i < length; ++i) {
                let index = _getRandomInt(0, parts.length - 1);
                id += parts[index];
            }

            return id;
        },
        updateSortOrder() {
            this.items.map((item, index) => {
                item.sort_order = index + 1;
            });
        },
        newItem() {
            this.currentItem = this.defaultItem();
            this.mode = 'create';
        },
        updateItems(items, currentItem) {
            this.is_dirty = true;
            currentItem.is_dirty = true;

            // Is this a new item or are we updating an existing item
            if (items.includes(currentItem)) {
                items[currentItem] = currentItem;
            } else {
                currentItem.sort_order = items.length + 1;
                items.push(currentItem);
            }

            return items;
        },
        saveItem() {
            // Make sure the current item has an id in which to track it
            this.currentItem.id = this.currentItem.id || this.generateId();

            let currentItem = this.currentItem;
            if (currentItem.parent_id === null) { // this is a parent item
                this.items = this.updateItems(this.items, currentItem);

            } else { // this is a child item
                // get the parent of this child item
                let parentItem = this.items.find(function (item) {
                    return item.id == currentItem.parent_id;
                });

                if (parentItem !== undefined) {
                    // update this child item in its parent
                    parentItem.children = this.updateItems(parentItem.children, currentItem);

                    // update the items list with the just-updated parent item
                    this.items = this.updateItems(this.items, parentItem);
                }
            }

            // Reset the current item as we are done with it
            this.currentItem = this.defaultItem();
        },
        editItem(item, index) {
            this.currentItem = item;
            this.mode = 'edit';
        },
        deleteItem(item, index) {
            this.deleteItems(this.items, index);
            this.updateState();
        },
        editChildItem(childItem, childIndex, parentItem, parentIndex) {
            this.currentItem = childItem;
            this.mode = 'edit';
        },
        deleteChildItem(childItem, childIndex, parentItem, parentIndex) {
            parentItem.children = this.deleteItems(parentItem.children, childIndex);
            this.items = this.updateItems(this.items, parentItem);
            this.updateState();
        },
        deleteItems(items, itemIndex) {
            this.$delete(items, itemIndex);

            return items;
        },
        updateState() {
            if (!this.items.length) {
                this.state = 'no-data';
                this.message = 'Please complete the form to add new items'
            }
        },
        checkForExistingItems() {
            if (this.menu && this.menu.items) {
                this.items = this.menu.items;
            }
        },
        defaultItem() {
            return {
                id : null,
                name : null,
                type : 'internal',
                url : null,
                target : '_self',
                parent_id : null,
                menu_group_id : null,
                entity_type : null,
                entity_id : null,
                entity_route : null,
                is_new : true,
            }
        },
    },
    mounted() {
        this.checkForExistingItems();
        this.updateState();

        let form = document.getElementById('menu-builder-form');
        if (form.length) {
            form.addEventListener('submit', (e) => {
                this.is_dirty = false;
                window.removeEventListener('beforeunload', () => {
                });
            });
        }
        window.addEventListener('beforeunload', (e) => {
            if (this.is_dirty) {
                e.preventDefault();
                e.returnValue = 'Leave page?, changes that you made may not be saved.';
            }
        });
    }
}
</script>
