<template>
	<div class="map-wrapper">
		<img src="g7-map.svg">
		<div class="rooms">
			<span class="title">Rooms</span>
			<ul>
				<li
					:key="room_nr"
					v-for="[room_nr, room] in Object.entries(rooms)"
				>
					<span class="room-nr">{{ room_nr }}. {{ room }}</span>
					<span
						:style="{color: get_temperature_color(minion_data_map[room_nr])}"
						v-if="minion_data_map[room_nr] !== undefined"
					>
						{{ minion_data_map[room_nr] }}°C
					</span>
				</li>
			</ul>
		</div>
	</div>
</template>

<script lang="ts">
import { defineComponent, Ref, ref } from "vue";

type MinionInfo = {
	ip_address: string
	position: number
};

type MinionInfoResponse = {
	data: MinionInfo[]
}

type MinionTemperatureResponse = {
    data: { temperature: number } | null
    error: string | null
}

const rooms = {
	1: "Studio / G3",
	2: "Studio 1",
	3: "Hall",
	4: "Studio 2",
	5: "Studio 3",
	6: "Grupprum",
	7: "Verkstad",
	8: "Serverrum",
	9: "Kurator",
	10: "Pannrum",
	11: "Toalett",
	12: "Inspelningsbås",
	13: "G2",
	14: "Trapphus"
};

const temperature_colors = {
	extremly_hot: "#d00000",
	hot: "#dc2f02",
	mildly_hot: "#e85d04",
	mild: "#52b69a",
	cold: "#0077b6",
	freezing_cold: "#168aad"
};

export default defineComponent(
	{
		name: "G7Map",
		data() {
			return {
				rooms: rooms
			};
		},
		methods: {
			get_temperature_color(temperature: number) {
				if(temperature < 10) {
					return temperature_colors.freezing_cold;
				}

				if(temperature < 20) {
					return temperature_colors.cold;
				}

				if(temperature > 27) {
					return temperature_colors.mildly_hot;
				}

				if(temperature > 31) {
					return temperature_colors.hot;
				}

				if(temperature > 38) {
					return temperature_colors.extremly_hot;
				}

				return temperature_colors.mild;
			}
		},
		setup(props) {
			const minion_data_map: Ref<Record<number, number>> = ref({});

			async function fetch_minion_ip_addresses() {
				let response: Response;

				const api_endpoint_url =
					`${window.location.protocol}//${window.location.host}/api/v1/minions`;

				try {
					response = await fetch(api_endpoint_url);
				}
				catch (err) {
					const error = err as Error;

					throw Error(`Failed to fetch minion IP addresses. ${error.message}`);
				}

				const data = await response.json() as MinionInfoResponse;

				if(!response.ok) {
					throw Error(
						"Failed to get minion IP addresses. Responded with status " +
						`${response.status}`
					);
				}

				return data.data;
			}

			async function fetch_minion_temperature(
				minion_name: string,
				minion_ip_address: string
			) {
				let response: Response;

				try {
					response = await fetch(`http://${minion_ip_address}`);
				}
				catch (err) {
					const error = err as Error;

					throw Error(
						`Failed to fetch temperature for minion "${minion_name}". ` +
                        `${error.message}`
					);
				}

				const data = await response.json() as MinionTemperatureResponse;

				if(!response.ok) {
					if(data.error !== null) {
						throw Error(
							`Minion "${minion_name}" responded with status ` +
                                `${response.status} and error "${data.error}"`
						);
					}

					throw Error(
						`Minion "${minion_name}" responded with status ` +
                                `${response.status} and a unknown error`
					);
				}

				if(data.data == null) {
					throw Error(`Minion "${minion_name}" has no data in response`);
				}

				return data.data.temperature;
			}

			async function fetch_all_minion_data() {
				const minion_info_arr = await fetch_minion_ip_addresses();

				const minion_data_map_buf: Record<number, number> = {};

				for(const minion_info of minion_info_arr) {
					const temperature =
						await fetch_minion_temperature("lol", minion_info.ip_address);

					minion_data_map_buf[minion_info.position] = temperature;
				}

				minion_data_map.value = minion_data_map_buf;
			}

			return { minion_data_map, fetch_all_minion_data };
		},
		created() {
			this.fetch_all_minion_data();
		}
	}
);
</script>

<style scoped lang="scss">
@use "sass:map";

@use "@/scss/colors";

@import "@/scss/breakpoints";

.map-wrapper {
    display: flex;
    flex-wrap: wrap;
    row-gap: 5em;
    column-gap: 10em;

    img {
        max-width: 50%;
    }

    .rooms {
        min-width: 40%;

        ul li {
			line-height: 2.25em;
			list-style: none;

            .room-nr {
                margin-right: 1.5em;
            }
        }

        .title {
            font-size: 2rem;
            font-weight: 700;
            color: colors.$primary;
        }
    }
}

@media (max-width: map.get($breakpoints, "xl")) {
    .map-wrapper img {
        max-width: 90%;
    }
}
</style>
