<script>
import { defineNuxtComponent } from 'nuxt/app';

import SlideDetails from './WeatherModals/SlideDetails.vue';
import AddLocation from './WeatherModals/AddLocation.vue';
import DeleteLocation from './WeatherModals/DeleteLocation.vue';

export default defineNuxtComponent({
    name: 'WeatherDashboard',
    components: {
        SlideDetails,
        AddLocation,
        DeleteLocation,
    },
    data: () => ({
        apiBaseURL: 'http://10.1.1.2:8880',
        apiURL: '',
        addModalOpen: false,
        addConfirmModalOpen: false,
        deleteModalOpen: false,
        detailsModalOpen: false,
        selectedLocationID: false,
        userId: 1,
        runtimeCode: 0,
        locID: null,
        locations: [],
        databaseLocations: [],

        weatherData: [],
        weatherIcons: {
            1: [0],
            2: [57, 63, 65, 66, 67, 73, 75, 77, 80, 81, 82, 85, 86, 95, 96, 99],
            3: [1, 2, 3],
            4: [45, 48],
            5: [51, 53, 61, 66, 71, 55, 56],
        },
    }),

    /**
     * Asynchronously fetches weather data for each location on mount.
     *
     * @return {Promise<void>} A promise that resolves once weather data is fetched.
     */
    async mounted() {
        this.locations = [];
        await this.getDatabaseLocations(true);
        if (this.locations.length > 0) {
            for (let i = 0; i < this.locations.length; i++) {
                await this.fetchWeatherData(false, this.locations[i]);
            }
        }
    },
    methods: {
        /**
         * Adds a new location ID to the locations array.
         *
         * @param {type} idx - The index of the new location ID to add.
         * @return {type}
         */
        async addNewLocID(idx) {
            await this.locations.push(idx);
        },

        /**
         * Removes the input location ID from the locations array.
         *
         * @param {type} input - description of parameter
         * @return {type} description of return value
         */
        removeLocID(input) {
            this.locations = this.locations.filter((l) => l !== input);
        },

        /**
         * Sets the specified modal type to open.
         *
         * @param {type} modalType - The type of modal to open
         * @return {type}
         */
        openModal(modalType) {
            this[`${modalType}ModalOpen`] = true;
        },

        /**
         * Closes a specific modal and performs additional actions if needed.
         *
         * @param {type} modalType - The type of modal to close
         */
        closeModal(modalType) {
            this[`${modalType}ModalOpen`] = false;
        },

        /**
         * A description of the entire function.
         *
         * @param {type} bulk - description of parameter
         * @param {type} location - description of parameter
         * @return {type} description of return value
         */
        async fetchWeatherData(bulk = false, location = null) {
            await this.getDatabaseLocations(true);
            this.apiURL = '';
            if (bulk) {
                this.apiURL = `${this.apiBaseURL}/locations?places=${this.locations}`;
            } else {
                this.apiURL = `${this.apiBaseURL}/locations/${location}`;
            }

            await fetch(this.apiURL)
                .then((res) => res.json())
                .then((json) => {
                    for (let d in json) {
                        if (!(d in this.locations.values())) {
                            const mergedJSON = Object.assign({}, this.weatherData, json);
                            this.weatherData = mergedJSON;
                        }
                    }
                });
        },

        /**
         * Returns the weather icon for the specified WMO code.
         *
         * @param {type} wmoCode - description of parameter
         * @return {type} description of return value
         */
        getWeatherIcon(wmoCode) {
            for (let idx in this.weatherIcons) {
                if (this.weatherIcons[idx].includes(wmoCode)) {
                    return '/' + idx + '.svg';
                }
            }
        },

        /**
         * Returns the locations from the database and the configured locations by the user.
         *
         * @param {type} configured - description of parameter
         * @return {type} description of return value
         */
        async getDatabaseLocations(configured = false) {
            if (configured == true) {
                this.locations = [];
                this.apiURL = `${this.apiBaseURL}/locations?places=configured&user=${this.userId}`;
                await fetch(this.apiURL)
                    .then((res) => res.json())
                    .then((json) => {
                        for (let idx in json) {
                            this.locations.push(json[idx].location_id);
                        }
                    });
                this.apiURL = '';
            } else {
                this.apiURL = `${this.apiBaseURL}/locations?places=database_locations`;
                await fetch(this.apiURL)
                    .then((res) => res.json())
                    .then((json) => {
                        this.databaseLocations = json;
                    });
                this.apiURL = '';
            }
        },

        /**
         * A function that takes a date in the format 'dd/mm/yyyy' and returns the day of the week.
         *
         * @param {type} date - description of parameter
         * @return {type} description of return value
         */
        getDay(date) {
            let isoDate = date.split('/');
            date = isoDate[2] + '-' + isoDate[1] + '-' + isoDate[0];
            const names = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
            const day = new Date(date).getDay();
            return names[day];
        },

        /**
         * Displays a notification with the specified type and input.
         *
         * @param {type} type - description of parameter
         * @param {type} input - description of parameter
         * @return {type} description of return value
         */
        displayNotification(type, input) {
            if (type == 'add') {
                var info = input.name + ', ' + input.country + ' was added succesfully to the list.';
            }

            useToast().add({
                id: 'location_add',
                title: 'Locations updated.',
                description: info,
                background: 'bg-white dark:bg-gray-900',
                shadow: 'shadow-lg',
                rounded: 'rounded-lg',
                padding: 'p-4',
                gap: 'gap-3',
                timeout: 5000,
            });
        },
    },
});
</script>

<template>
    <div class="w-screen mx-auto pt-8">
        <div class="max-w-5xl mx-auto container">
            <div class="section">
                <div>
                    <img class="float-left w-10 mr-2" src="/icon.svg" alt="dashboard icon" />
                    <div class="text-container">
                        <p class="text-md pt-1.5 font-semibold font-sans align-middle">Weather App</p>
                    </div>
                    <div class="min-h-10 mt-14 container">
                        <div>
                            <p class="float-left font-semibold font-sans w-8 mr-2 text-left text-3xl">Locations</p>
                            <div>
                                <button
                                    class="float-right text-justify text-xs bg-linkwater-100 text-gray-900 hover:bg-linkwater-300 font-bold py-2 px-4 rounded-md"
                                    @click="openModal('add')"
                                >
                                    + Add Location
                                </button>
                            </div>
                        </div>
                    </div>
                    <div class="mt-5 container overflow-visible">
                        <!--
                        Component: AddLocation
                        Description: This component renders a modal for adding a location to the dashboard.
                        Props:
                            - addModalOpen: boolean. Determines if the modal is open or not.
                            - locations: Array. List of locations from the database.
                            - weatherData: Array. List of locations from the API.
                            - databaseLocations: Array. List of locations from the database.
                            - locID: String|Null. ID of the location from the API.
                        Events:
                            - close-modal: Emitted when the modal is closed.
                            - close-prevented: Emitted when the modal is closed by preventing the default action.
                        -->
                        <div>
                            <div v-if="this.addModalOpen">
                                <AddLocation
                                    @close-modal="closeModal('add')"
                                    @close-prevented="closeModal('add')"
                                    :modalState="this.addModalOpen"
                                    :locations="this.locations"
                                    :weatherData="this.weatherData"
                                    :databaseLocations="this.databaseLocations"
                                    :locID="this.locID"
                                    :apiBaseURL="this.apiBaseURL"
                                />
                            </div>
                        </div>

                        <!--
                        Component: DeleteLocation
                        Description: This component renders a modal for deleting a location from the dashboard.
                        Props:
                            - deleteModalOpen: boolean. Determines if the modal is open or not.
                            - weatherData: Array. List of locations from the API.
                            - locations: Array. List of locations from the database.
                            - locID: String|Null. ID of the location from the API.
                        Events:
                            - close-modal: Emitted when the modal is closed.
                            - close-prevented: Emitted when the modal is closed by preventing the default action.
                        -->
                        <div>
                            <div v-if="this.deleteModalOpen">
                                <DeleteLocation
                                    @close-modal="closeModal('delete')"
                                    @close-prevented="closeModal('delete')"
                                    :modalState="this.deleteModalOpen"
                                    :weatherData="this.weatherData"
                                    :locations="this.locations"
                                    :locID="this.locID"
                                    :apiBaseURL="this.apiBaseURL"
                                />
                            </div>
                        </div>
                        <!--
                        Component: SlideDetails
                        Description: This component renders a modal for viewing the details of a specific location.
                        Props:
                            - detailsModalOpen: boolean. Determines if the modal is open or not.
                            - weatherData: Array. List of locations from the API.
                            - locID: String. ID of the location from the API.
                        Events:
                            - close-modal: Emitted when the modal is closed.
                            - close-prevented: Emitted when the modal is closed by preventing the default action.
                        -->
                        <div>
                            <div v-if="this.detailsModalOpen">
                                <SlideDetails
                                    @close-modal="closeModal('details')"
                                    @close-prevented="closeModal('details')"
                                    :modalState="this.detailsModalOpen"
                                    :weatherData="this.weatherData"
                                    :locID="this.locID"
                                />
                            </div>
                        </div>

                        <!--
                        Table: Weather Data Table
                        Description: This table displays the weather data for each location.
                        Props:
                            - weatherData: Object. List of locations from the API.
                        -->
                        <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
                            <!-- Table Header -->
                            <thead class="text-md text-gray-100 bg-mineshaft-900">
                                <tr>
                                    <th scope="col" class="px-6 py-3">Location</th>
                                    <th scope="col" class="px-6 py-3">Temperature</th>
                                    <th scope="col" class="px-6 py-3">Rainfall</th>
                                    <th scope="col" class="px-6 py-3"></th>
                                </tr>
                            </thead>
                            <!-- Table Body -->
                            <tbody>
                                <!-- Check if weatherData is not empty -->
                                <template v-if="Object.keys(this.weatherData) != 0">
                                    <!-- Loop through each location in weatherData -->
                                    <tr
                                        v-for="loc in this.weatherData"
                                        class="bg-woodsmoke-950 border-tuatara-900 border-b-2 text-gray-300"
                                    >
                                        <!-- Location Name -->
                                        <td class="px-6 py-4">
                                            <div
                                                class="cursor-pointer"
                                                @click="
                                                    openModal('details');
                                                    this.locID = loc.id;
                                                "
                                            >
                                                <img
                                                    class="float-left w-8 mr-3"
                                                    :src="getWeatherIcon(loc.data.current.weather_code)"
                                                    alt="weather icon"
                                                />
                                                <div class="text-container">
                                                    <p class="text-sm pt-1.5 font-semibold font-sans align-middle">
                                                        {{ loc.data.location.name }}
                                                    </p>
                                                </div>
                                            </div>
                                        </td>
                                        <!-- Temperature -->
                                        <td class="px-6 py-4">{{ Math.ceil(loc.data.current.temperature_2m) }} °C</td>
                                        <!-- Rainfall -->
                                        <td class="px-6 py-4">
                                            {{ Math.round(loc.data.current.rain * 100) / 100 }} mm
                                        </td>
                                        <!-- Delete Button -->
                                        <td class="float-right px-6 py-4">
                                            <UButton
                                                icon="i-heroicons-trash"
                                                size="sm"
                                                color="mineshaft"
                                                square
                                                variant="ghost"
                                                @click="
                                                    openModal('delete');
                                                    this.locID = loc.id;
                                                "
                                            />
                                        </td>
                                    </tr>
                                </template>
                                <!-- Show message if weatherData is empty -->
                                <template v-else>
                                    <tr class="bg-woodsmoke-950 border-tuatara-900 border-b-2 text-gray-300">
                                        <td colspan="4" class="px-6 pt-10 pb-8">
                                            <p class="text-pretty text-center">Please add a location</p>
                                        </td>
                                    </tr>
                                </template>
                            </tbody>
                        </table>
                        <!-- Notification Component -->
                        <UNotifications />
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- <strong>DEBUG</strong>
    <div class="pt-10">
        <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
            <thead class="text-md text-gray-100 bg-mineshaft-900">
                <tr>
                    <th scope="col" class="px-6 py-3">Location</th>
                    <th scope="col" class="px-6 py-3">Temperature</th>
                    <th scope="col" class="px-6 py-3">Rainfall</th>
                    <th scope="col" class="px-6 py-3"></th>
                </tr>
            </thead>
            <tbody>
                <template v-if="locations.length > 0" v-for="loc in this.weatherData">
                    <tr colspan="4" class="w-full bg-woodsmoke-950 border-tuatara-900 border-b-2 text-gray-300">
                        <td class="w-full">
                            <pre>{{ loc }}</pre>
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
    </div>
    <strong>DEBUG</strong> -->
</template>
