<template>
  <div class="relative h-full bg-gray-100">
    <div
      class="absolute top-0 left-0 z-10 rounded-br-md border-b-2 border-r-2 border-gray-200 bg-white px-2 py-2 shadow-lg"
    >
      <div class="flex flex-row items-center space-x-4 px-4">
        <div class="flex flex-row items-center space-x-4">
          <label for="building">Building:</label>
          <select
            id="building"
            class="rounded-sm border-gray-300 py-1 focus:ring-2 focus:ring-blue-200"
            v-model="selectedBuildingId"
            @change="buildingSelected()"
          >
            <option v-for="building of buildings" :value="building.id">
              {{ building.displayName }}
            </option>
          </select>
        </div>
        <div
          class="flex flex-row items-center space-x-4"
          v-if="selectedBuildingId"
        >
          <label for="floor">Floor:</label>
          <select
            id="floor"
            class="rounded-sm border-gray-300 py-1 focus:ring-2 focus:ring-blue-200"
            v-model="selectedFloorId"
          >
            <option v-for="floor of floors" :value="floor.id">
              {{ floor.displayName }} ({{ floor.number }})
            </option>
          </select>
        </div>
        <div v-if="selectedFloorId">{{ status }}</div>
      </div>
    </div>
    <HousePlanner
      v-if="selectedFloorId"
      editable
      ref="plannerRef"
      :key="`planner-${selectedFloorId}`"
      :floor-document="floorPlan"
      @update="(layers, rooms) => updateDocument(layers, rooms)"
      @edited="status = 'Modified'"
    />
    <div
      class="flex h-full w-full select-none items-center justify-center text-lg"
      v-else
    >
      <span class="font-bold uppercase text-gray-300"
        >Choose a floor to edit from the top left</span
      >
    </div>
  </div>
</template>

<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { computed, onMounted, ref } from 'vue';
import { defaultRoomData } from '../components/house-planner/helpers/default-room';
import HousePlanner from '../components/house-planner/HousePlanner.vue';
import { FloorDocument } from '../components/house-planner/interfaces/floor-document.interface';
import { UpsertRoomItem } from '../interfaces/room.interfaces';
import { Line } from '../modules/house-planner/interfaces';
import { useBuildingStore } from '../store/building.store';
import extractLinePoints from '../utils/extract-line-points';
const building = useBuildingStore();

const { buildings, floors } = storeToRefs(building);
const selectedBuildingId = ref<number>();
const selectedFloorId = ref<number>();
const status = ref('No changes');
const plannerRef = ref<InstanceType<typeof HousePlanner>>();

const currentFloor = computed(
  () =>
    selectedFloorId.value &&
    floors.value.find((floor) => floor.id === selectedFloorId.value)
);
const floorPlan = computed(
  () =>
    currentFloor.value &&
    Object.assign({
      ...defaultRoomData,
      ...JSON.parse(currentFloor.value.plan || '{}'),
      id: selectedFloorId.value,
    })
);

const buildingSelected = async () => {
  if (selectedBuildingId.value == null) return;
  selectedFloorId.value = undefined;
  await building.getFloors(selectedBuildingId.value);
};

const updateRooms = async (data: FloorDocument, rooms: Line[]) => {
  if (
    !selectedBuildingId.value ||
    !selectedFloorId.value ||
    !currentFloor.value
  )
    return data;

  const extractedRooms: UpsertRoomItem[] = rooms.map((room) => ({
    id: room.databaseId,
    canvasObjectId: room.id,
    displayName: room.name,
    plan: JSON.stringify({ polygon: extractLinePoints(room) }),
  }));

  if (!extractedRooms.length) {
    return data;
  }

  const createdRooms = await building.upsertFloorRooms(
    selectedBuildingId.value,
    currentFloor.value.number,
    extractedRooms
  );

  if (createdRooms?.length) {
    createdRooms.forEach((room) => {
      if (!room.canvasObjectId || !room.id) return;
      rooms.forEach((existing) => {
        if (existing.id !== room.canvasObjectId) return;
        existing.databaseId = room.id;
      });
    });

    if (plannerRef.value) {
      data = plannerRef.value.updateLocalDocument();
    }
  }

  return data;
};

const updateDocument = async (data: FloorDocument, rooms: Line[]) => {
  if (
    !selectedBuildingId.value ||
    !selectedFloorId.value ||
    !currentFloor.value ||
    status.value === 'Saving...'
  )
    return;

  status.value = 'Saving...';
  try {
    data = await updateRooms(data, rooms);

    // Prevent useless requests
    const floorPlan = JSON.stringify(data);
    if (currentFloor.value.plan === floorPlan) {
      status.value = 'Saved!';
      return;
    }

    await building.saveFloor(
      selectedBuildingId.value,
      currentFloor.value.number,
      {
        plan: floorPlan,
      }
    );
    status.value = 'Saved!';
  } catch (e) {
    console.error(`Failed to save floor document: ${(e as Error).stack}`);
    status.value = 'Failed to save!';
  }
};

onMounted(() => {
  floors.value = [];
  building.getBuildings();
});
</script>
