<script lang="ts">
import { defineComponent, ref, Ref, SetupContext, watch } from 'vue';
import PointCloud from '../components/pointcloud.vue';
import VueDatePicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css'
import Map from '../components/map.vue';
import FileUpload from '../components/fileUpload.vue';
import Message from '../components/message.vue';
import { useRoute } from 'vue-router'

type DriverType = {
  id: number
  name: string
}

type Track = {
  id: number
  name: string
  driver: DriverType
  time: Date
}

type GeoJSONFeature = {
  type: "Feature";
  geometry: {
    type: "LineString";
    coordinates: number[][];
  };
  properties: {
    name: string;
    driver: string;
  };
};

type GeoJSON = {
  type: "FeatureCollection";
  features: GeoJSONFeature[];
};

export default defineComponent({
  name: 'map',
  components: { PointCloud, VueDatePicker, Map, FileUpload, Message },
  setup(_, { emit }: SetupContext) {
    const showMap: Ref<boolean> = ref(false);
    const showCloud: Ref<boolean> = ref(false);
    const search: Ref<boolean> = ref(false);
    const showUpload: Ref<boolean> = ref(false);
    const tracks: Ref<Track[]> = ref([])
    const searchedTracks: Ref<Track[]> = ref([])
    const startSearchDate = ref();
    const endSearchDate = ref();
    const mapData: Ref<GeoJSON | null> = ref(null);
    const renderSearchOnMap: Ref<Boolean> = ref(false);
    const multipleTracks: Ref<Boolean> = ref(false);
    const trackid: Ref<number> = ref(0);
    const isLoading:Ref<boolean> = ref(false);

    // values for UI Information distribution
    const messageType: Ref<string> = ref("");
    const message: Ref<string> = ref("");
    const route = useRoute()

    watch(() => route.params.id, (id) => {
      loadTrack(id)
    })

    const loadTrack = async (id: number) => {
      showCloud.value = false;
      search.value = false;
      showUpload.value = false;
      isLoading.value = true;

      trackid.value = id

      const headers: Headers = new Headers();
      headers.set('Content-Type', 'application/json');
      headers.set('Accept', 'application/json');

      const request: RequestInfo = new Request("http://localhost:5000/track?id=" + id, {
        method: "GET",
        headers: headers
      });

      try {
        var response = await fetch(request);

        if (response.ok) {
          showMap.value = true;
          isLoading.value = false;
          mapData.value = await response.json();
        } else {

          alert(`loading tracks failed: ${await response.text()}`)
          isLoading.value = false;
          console.log(await response.text());
          messageType.value = "error";
          message.value = `loading tracks failed: ${await response.text()}`;
        }
      } catch (error) {

        alert(`loading tracks failed with error: ${error}`)
        console.error("loading tracks failed with error:", error);
        messageType.value = "error";
        message.value = `loading tracks failed with error: ${error}`;
      }
    };

    // handles deleting tracks
    // note: deleting tracks takes a while due to their waypoints this can take a while and its not a bug
    const deleteTrack = async (trackID: number) => {
      const headers: Headers = new Headers()
      headers.set('Content-Type', 'application/json')
      headers.set('Accept', 'application/json')

      const requestBody = JSON.stringify({ id: trackID });

      const request: RequestInfo = new Request("http://localhost:5000/track", {
        method: "DELETE",
        headers: headers,
        body: requestBody
      })

      var response = await fetch(request)
      if (!response.ok) {
        console.log(await response.text())
        messageType.value = "error";
        message.value = `deleting track failed with error: ${await response.text()}`;
        getTracks()
      } else {

        alert("deleted track")
        console.log(await response.text())
        messageType.value = "success";
        message.value = `deleted track`;
      }

    }

    const getTracks = async () => {
      const headers: Headers = new Headers()
      headers.set('Content-Type', 'application/json')
      headers.set('Accept', 'application/json')

      const request: RequestInfo = new Request("http://localhost:5000/track", {
        method: "GET",
        headers: headers
      })

      var response = await fetch(request)
      // make sure the request was successfull
      if (response.ok) {
        var jsonBody = await response.json()

        // convert vehicles from json response to processable data
        for (let i = 0; i < jsonBody.length; i++) {
          tracks.value.push({ id: jsonBody[i]["id"], name: jsonBody[i]["name"], driver: { name: "", id: 0 }, time: new Date(Date.now()) })
        }
      } else {

        alert(`loading track list failed with error: ${error}`)
        console.log(await response.text())
        messageType.value = "error";
        message.value = `loading track list failed with error: ${error}`;
      }
    }

    const searchTracks = async () => {
      const headers: Headers = new Headers()
      headers.set('Content-Type', 'application/json')
      headers.set('Accept', 'application/json')
      isLoading.value = true;
      showMap.value = false;
      search.value = false;
      showCloud.value = true;
      showUpload.value = false;
      multipleTracks.value = false;

      if (startSearchDate.value == null || endSearchDate.value == null) {
        messageType.value = "error";
        message.value = "please give all required infos";
        return;
      }

      const request: RequestInfo = new Request("http://localhost:5000/track?start=" + startSearchDate.value + "&end=" + endSearchDate.value, {
        method: "GET",
        headers: headers
      })

      var response = await fetch(request)
      // make sure the request was successfull
      if (response.ok) {
        var jsonBody = await response.json()
        console.log(jsonBody)
        searchedTracks.value = [];

        // convert vehicles from json response to processable data
        for (let i = 0; i < jsonBody.length; i++) {
          let track = jsonBody[i]
          console.log(`track: ${jsonBody[i]["name"]}`)
          searchedTracks.value.push({
            id: track["id"],
            name: track["name"],
            driver: {
              name: track["driver"]["name"],
              id: track["driver"]["id"]
            },
            time: track["time"]
          })
        }
        isLoading.value = false;
        showCloud.value = true;

      } else {
        
        alert(`searching tracks failed: ${await response.text()}`)
        messageType.value = "error";
        message.value = `searching tracks failed: ${await response.text()}`;
      }

      if (renderSearchOnMap.value) {
        multipleTracks.value = true;
        isLoading.value = true;
        showMap.value = true;
        showCloud.value = false;

        searchedTracks.value.forEach(async track => {
          setTimeout(async () => {
            await loadTrack(track.id);
          }, 500)
        });

        isLoading.value = false;
      }
    }

    getTracks()

    return {
      showMap,
      showCloud,
      search,
      tracks,
      loadTrack,
      getTracks,
      searchedTracks,
      searchTracks,
      startSearchDate,
      endSearchDate,
      renderSearchOnMap,
      mapData,
      showUpload,
      multipleTracks,
      trackid,
      message,
      messageType,
      deleteTrack,
      getTracks,
      isLoading
    };
  },
});
</script>


<template>
  <Message v-if="type == 'none'" :type="messageType" :message="message" @close="message = ''; messageType = 'None'">
  </Message>
  <FileUpload v-if="showUpload" @close="showUpload = false;" @response="tracks=[]; getTracks();" :drivers="[]"
    style="position:absolute; top: 30VH; width: 60%; left:25%;"></FileUpload>
  <div class="grid grid-flow-col auto-cols-max gap-4">
    <div>
      <ul class="menu menu-xs bg-base-200 rounded-lg w-full max-w-xs overscroll-auto">
        <li> <a v-on:click="showUpload = true; showMap = false; showCloud = false; search = false;"> upload file </a>
        </li>
        <li> <a v-on:click="search = true; showMap = false; showCloud = false; showUpload = false;"> filter track </a>
        </li>
        <li>
          <div class="divider"></div>
        </li>
        <li v-if="tracks.length == 0">
          <div class="skeleton h-4 w-full"></div>
        </li>
        <li v-for="track in tracks"> 
          <span><a style="line-height: 50px; height:50px;" v-on:click="loadTrack(track.id); multipleTracks = false; showMap=false;"> {{ track.name }}</a>
            <button style="width:50px; float:right;" class="btn btn-error" v-on:click="deleteTrack(track.id); tracks=[]; getTracks();">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
                  class="bi bi-trash3-fill" viewBox="0 0 16 16">
                  <path
                    d="M11 1.5v1h3.5a.5.5 0 0 1 0 1h-.538l-.853 10.66A2 2 0 0 1 11.115 16h-6.23a2 2 0 0 1-1.994-1.84L2.038 3.5H1.5a.5.5 0 0 1 0-1H5v-1A1.5 1.5 0 0 1 6.5 0h3A1.5 1.5 0 0 1 11 1.5m-5 0v1h4v-1a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5M4.5 5.029l.5 8.5a.5.5 0 1 0 .998-.06l-.5-8.5a.5.5 0 1 0-.998.06m6.53-.528a.5.5 0 0 0-.528.47l-.5 8.5a.5.5 0 0 0 .998.058l.5-8.5a.5.5 0 0 0-.47-.528M8 4.5a.5.5 0 0 0-.5.5v8.5a.5.5 0 0 0 1 0V5a.5.5 0 0 0-.5-.5" />
                </svg>
              </button>
          </span>
        </li>
      </ul>
    </div>
    <div v-if="isLoading">
      <h1 class="title text-center	" style="text-align: center;"> map is loading: <span class="loading loading-spinner loading-lg"></span> </h1>
    </div>
    <div style="width: 65%; margin-left: 5%;">
      <PointCloud :routes="searchedTracks" style="border-radius: 10px;" v-if="showCloud && !search"></PointCloud>
    </div>
    <div v-if="!showMap && !showCloud && search" style="margin-left: 20%; display:flex;">
      <div>
        start time
        <input class="datepicker" type="date" id="startdate" name="startdate" v-model="startSearchDate">
      </div>
      <div style="margin-left: 5%;">
        end time
        <input class="datepicker" type="date" id="enddate" name="enddate" v-model="endSearchDate">
      </div>
      <div style="margin-left: 5%;">
        show on map:
        <input type="checkbox" class="toggle" v-model="renderSearchOnMap" />
      </div>
      <button v-on:click="searchTracks" class="btn btn-success"
        style="margin-left: 5%; height:60px; width:120px;">Search</button>
    </div>
    <div v-if="showMap && !search && !showCloud">
      <Map :track="trackid" :multiple="multipleTracks" :geoJsonData="mapData"
        style="width: 68vw; margin-left: 15%; border-radius: 10px; border: 1px solid #95a5a6;"></Map>
    </div>
  </div>
</template>

<style scoped>
input.datePicker {
  padding: 5px;
  border-radius: 5px;
  ;
}
</style>