<template>
  <div class="popup" :class="{ hidden: !point }" ref="popup">
    <div class="popup-content" v-if="point">
      <div class="header">
        <button @click="$emit('close')" title="Close">✕</button>
      </div>
      <div class="point-info">
        <h2 class="address" v-if="point.address">{{ point.address }}</h2>
        <h2 class="latlng" v-else>
          <a :href="osmUrl" target="_blank" rel="noopener noreferrer">
            <font-awesome-icon icon="fas fa-map-marker-alt" />
            {{ point.latitude }}, {{ point.longitude }}
          </a>
        </h2>
        <p class="latlng" v-if="point.address">
          <a :href="osmUrl" target="_blank" rel="noopener noreferrer">
            <font-awesome-icon icon="fas fa-map-marker-alt" />
            {{ point.latitude }}, {{ point.longitude }}
          </a>
        </p>
        <p class="altitude" v-if="point.altitude">
          <font-awesome-icon icon="fas fa-mountain" />
          {{ Math.round(point.altitude) }} m
        </p>

        <form class="description editor" @submit.prevent="editPoint" v-if="editDescription">
          <div class="row">
            <textarea
              :value="point.description"
              @keydown.enter="editPoint"
              @blur="onDescriptionBlur"
              ref="description"
              placeholder="Enter a description" />

            <button type="submit" title="Save">
              <font-awesome-icon icon="fas fa-save" />
            </button>
          </div>
        </form>

        <p class="description"
           :class="{ 'no-content': !point.description?.length }"
           @click="editDescription = true"
           v-else>
          <span class="icon">
            <font-awesome-icon icon="fas fa-edit" />
          </span>
          <span class="text">
            {{ point.description?.length ? point.description : 'No description' }}
          </span>
        </p>

        <p class="locality" v-if="point.locality">{{ point.locality }}</p>
        <p class="postal-code" v-if="point.postalCode">{{ point.postalCode }}</p>
        <p class="country" v-if="country">
          <span class="flag" v-if="countryFlag">{{ countryFlag }}&nbsp; </span>
          <span class="name">{{ country.name }}</span>,&nbsp;
          <span class="continent">{{ country.continent }}</span>
        </p>
        <p class="timestamp" v-if="timeString">{{ timeString }}</p>

        <div class="remove">
          <button title="Remove" @click="$emit('remove', point)">
            <font-awesome-icon icon="fas fa-trash-alt" />&nbsp; Remove
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import Map from 'ol/Map';
import Overlay from 'ol/Overlay';
import type { TCountryCode } from 'countries-list';
import { getCountryData, getEmojiFlag } from 'countries-list';

import Dates from '../mixins/Dates.vue';
import GPSPoint from '../models/GPSPoint';

export default {
  emit: ['close', 'edit', 'remove'],
  mixins: [Dates],
  props: {
    point: {
      type: [GPSPoint, null],
    },
  },

  data() {
    return {
      newValue: {} as GPSPoint,
      editDescription: false,
      popup: null as Overlay | null,
    }
  },

  computed: {
    country() {
      const cc = this.point?.country as string | undefined
      if (cc?.length) {
        return getCountryData(cc.toUpperCase() as TCountryCode)
      }

      return null
    },

    countryFlag() {
      return this.country ? getEmojiFlag(this.country.iso2 as TCountryCode) : null
    },

    osmUrl(): string {
      return `https://www.openstreetmap.org/?mlat=${this.point?.latitude}&mlon=${this.point?.longitude}`
    },

    timeString(): string | null {
      return this.formatDate(this.point?.timestamp)
    },
  },

  methods: {
    bindPopup(map: Map) {
      this.popup = new Overlay({
        element: this.$refs.popup as HTMLElement,
        autoPan: true,
      })

      // @ts-ignore
      map.addOverlay(this.popup)
    },

    editPoint() {
      this.newValue.description = (this.$refs.description as HTMLTextAreaElement).value
      this.$emit('edit', this.newValue)
      this.editDescription = false
    },

    onDescriptionBlur() {
      // Give it a moment to allow relevant click events to trigger
      setTimeout(() => {
        this.editDescription = false
      }, 100)
    },

    setPosition(coordinates: number[]) {
      if (this.popup) {
        this.popup.setPosition(coordinates)
      }
    },
  },

  watch: {
    point: {
      immediate: true,
      handler(point: GPSPoint | null) {
        if (point) {
          this.newValue = point
        }
      },
    },

    editDescription(edit: boolean) {
      if (edit) {
        this.$nextTick(() => {
          (this.$refs.description as HTMLTextAreaElement).focus()
        })
      }
    },
  },
}
</script>

<style lang="scss" scoped>
@import "ol/ol.css";

.popup {
  position: absolute;
  background: var(--color-background);
  min-width: 20em;
  padding: 1em;
  border-radius: 1em;
  box-shadow: 2px 2px 2px 2px var(--color-border);

  .popup-content {
    display: flex;
    flex-direction: column;
    gap: 1.5em;
  }

  .header {
    position: absolute;
    top: 0.5em;
    right: 0;

    button {
      background: none;
      border: none;
      color: var(--color-heading);
      font-size: 1.2em;
      cursor: pointer;

      &:hover {
        color: var(--color-accent);
      }
    }
  }

  &.hidden {
    padding: 0;
    border-radius: 0;
    box-shadow: none;
    width: 0;
    height: 0;
    min-width: 0;
    pointer-events: none;
  }

  p.latlng, p.altitude {
    font-size: 0.8em;
    margin: -0.25em 0 0.25em 0;
  }

  .description {
    cursor: pointer;

    &:hover {
      .icon {
        color: var(--color-accent);
      }
    }

    .icon {
      margin-right: 0.5em;
    }

    .text {
      font-style: italic;
    }

    &:not(.no-content) {
      .text {
        font-weight: bold;
      }

      .icon {
        color: var(--color-accent);
      }
    }

    &.no-content {
      font-size: 0.9em;
      opacity: 0.5;
    }

    textarea {
      min-height: 5em;
    }

    button {
      background: var(--color-accent);
      border: none;
      color: var(--color-accent);
      font-size: 0.9em;
      margin: 0;
      padding: 0.5em 1.5em;
      cursor: pointer;

      &:hover {
        color: var(--color-heading);
      }
    }
  }

  .timestamp {
    color: var(--color-heading);
    font-weight: bold;
    font-size: 0.9em;
  }

  .remove {
    font-size: 0.85em;
    margin-top: 0.5em;

    button {
      width: 100%;
      background: none;
      border: none;
      color: var(--vt-c-red-fg-light);
      margin-left: -0.5em;

      &:hover {
        color: var(--vt-c-red-fg-dark);
      }
    }
  }
}
</style>