<template>
    <div class="estimate-plan-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="">
            <div>
                <div v-if="items && items.length" :class="['has-items', state]">
                    <draggable
                        :list="items"
                        handle=".handle"
                        @update="updateSortOrder"
                    >
                        <transition-group name="list" tag="div">
                            <estimate-plan-item
                                v-for="(item, index) in orderedItems"
                                :key="item.id"
                                :index="index"
                                :item="item"
                                :existing-item="existingItem"
                                @editItem="editItem"
                                @updateItem="updateItem"
                                @deleteItem="deleteItem"
                            >
                            </estimate-plan-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>
                <estimate-plan-form
                    :new-item="newItem"
                    :mode="mode"
                    :itemscope="items"
                    @createItem="createItem"
                ></estimate-plan-form>
            </div>
        </div>
    </div>
</template>


<script>
import EstimatePlanForm from "./EstimatePlanForm";
import EstimatePlanItem from "./EstimatePlanItem";
import Draggable from 'vuedraggable';

export default {
    components : {
        EstimatePlanForm,
        EstimatePlanItem,
        Draggable
    },
    props : {
        estimatePlan : {type : Object},
    },
    computed : {
        orderedItems : function () {
            return _.orderBy(this.items, this.orderBy)
        }
    },
    data() {
        return {
            items : [],
            newItem : this.defaultItem(),
            existingItem : null,
            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;
            });
        },
        createItem() {

            let duplicate = this.findItemByArea(this.newItem);
            if (duplicate) {
                this.newItem.has_error = true;
                this.newItem.error_message = 'An item with the same area M2 already exists';

                return;
            }

            this.is_dirty = true;
            this.existingItem = null;

            // Set the id and add the new item to the items array
            this.newItem.id = this.generateId();
            this.newItem.is_new = true;
            this.newItem.sort_order = this.items.length + 1;
            this.items.push(this.newItem);

            // Reset the new item as we are done with it
            this.newItem = this.defaultItem();
            this.mode = 'create';
        },
        updateItem(item) {
            this.is_dirty = true;

            let index = this.findIndexById(item);
            let duplicate = this.findItemByArea(item);

            if (index !== -1 && duplicate) {
                this.items[index].has_error = true;
                this.items[index].error_message = 'An item with the same Area M2 already exists';
            }
        },
        findIndexById(item) {
            return this.items.findIndex(existing => existing.id === item.id);
        },
        findItemByArea(item) {
            return this.items.find((existing) => {
                // Skip the item with the same id
                if (item.id && parseInt(existing.id) === parseInt(item.id)) {
                    return false;
                }

                return parseFloat(existing.area_m2) === parseFloat(item.area_m2)
            });
        },
        editItem(item) {
            this.existingItem = item;
            this.mode = 'edit';
        },
        deleteItem(item) {
            let index = this.findIndexById(item);
            this.deleteItems(this.items, index);
            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.estimatePlan && this.estimatePlan.items) {

                // Set the items from the estimate plan
                this.items = this.estimatePlan.items;

                // Loop through each of the items and set the error state
                this.items.forEach((item) => {
                    item.has_error = false;
                    item.error_message = false;
                    item.sort_order = item.sort_order || this.items.length + 1;
                });
            }
        },
        defaultItem() {
            return {
                id : null,
                area_m2 : null,
                cost_m2 : null,
                sort_order : this.items && this.items.length > 0
                    ? this.items.length + 1
                    : 1,
                is_new : true,
                has_error : false,
                error_message : null,
            }
        },
    },
    mounted() {
        this.checkForExistingItems();
        this.updateState();

        let form = document.getElementById('estimate-plan-builder-form');
        if (form && 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>
