<template>
  <div class="fp-container">
    <div class="controls">
      <div class="btn-group" role="group">
        <button class="btn btn-sm btn-light" @click="zoomToFit">
          <i class="mdi mdi-arrow-expand-all"></i>
        </button>
      </div>
    </div>
    <div :id="`fp-${uid}`" class="floor-planner" />
  </div>
</template>

<script lang="ts">
import { Area } from './area'
import { PropType, defineComponent, nextTick } from 'vue'
import { Node, NodeData } from './node'
import { NodeList } from './nodelist'
import { NodeView } from './nodeview'

export default defineComponent({
  props: {
    backgroundImage: {
      type: String,
      required: true,
      default: ''
    },
    nodeList: {
      type: Array as PropType<NodeData[]>,
      required: true,
      default: []
    },
    addNodeOnDblClick: {
      type: Boolean,
      default: true
    }
  },

  data() {
    return {
      uid: Math.floor(Math.random() * 100000),
      area: undefined as undefined | Area,
      lastZoom: 0,
    }
  },

  mounted() {
    const container = document.getElementById(`fp-${this.uid}`)

    if (container) {
      nextTick(() => {
        const inner = container.querySelector('.floor-planner .inner');
        if (inner) {
          (inner as HTMLElement).style.backgroundImage = `url(${this.backgroundImage})`;
        }
      })

      const area = this.area = new Area(container, this.addNodeOnDblClick)

      if (this.nodeList && this.nodeList.length > 0) {
        this.nodeList.forEach((nodeData) => {
          const node = new Node(nodeData.id);
          node.position = [nodeData.x, nodeData.y];
          node.label = nodeData.label;
          node.color = nodeData.color;
          area.addNode(node, this.nodeClicked);
          const pinElement = container.querySelector(`.floor-planner .inner [class^="pin-${nodeData.id}"]`);
          if (pinElement) {
            (pinElement as HTMLElement).style.backgroundColor = nodeData.color;
          }
        });
      }

      this.initialZoom()
    }
  },

  methods: {
    nodeClicked(nodeView: NodeView, nodeList: NodeList, _e: MouseEvent) {
      nodeList.selected = nodeView
      this.$emit('node-clicked', { nodeView, nodeList });
    },
    zoomToFit() {
      const area = this.area;

      if (area && area.nodeList.nodes.length > 0) {
        const bound = area.nodeList.getBoundingBox()
        this.lastZoom = area.nodeList.getZoomToFit(bound)
        area.setTransform(this.lastZoom, - (bound.minX + bound.width / 2) * this.lastZoom + (area.viewport.width / 2), - (bound.minY + bound.height / 2) * this.lastZoom + (area.viewport.height / 2))
        area.applyZoom(this.lastZoom)
        area.update()
      }
    },
    initialZoom() {
      const area = this.area;

      if (area) {
        const defaultZoom = 1;
        area.setTransform(defaultZoom, 0, 0);
        area.applyZoom(defaultZoom);
        area.update();
      }
    },
  }
})
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss">
.fp-container {
  position: relative;

  .controls {
    position: absolute;
    z-index: 100;
    right: 10px;
    top: 10px;
  }

  .floor-planner {
    position: absolute;
    width: 100%;
    height: 300px;
    background-color: #ff000022;
    position: relative;
    overflow: hidden;
    top: 0;
    left: 0;

    .inner {
      background-size: contain;
      background-repeat: no-repeat;       
      position: absolute;
      width: 2560px;
      height: 1440px;
      border: solid 1px transparent;
      text-align: center;
      user-select: none;

      [class^="pin-"] {        
        --pin-size: 20px;
        border-radius: 50%;
        width: var(--pin-size);
        height: var(--pin-size);
        background-color: #ff0000AA;
        opacity: .7;
        cursor: pointer;
        font-size: calc(var(--pin-size) * 0.5);
        line-height: calc(var(--pin-size));
        margin-left: calc(var(--pin-size) / 2 * -1);
        margin-top: calc(var(--pin-size) / 2 * -1);
        color: white;
        font-weight: bold;

        &:hover {
          opacity: 1;
        }
      }
      .pin {
          &.selected {
          background-color: black !important;
          opacity: 1 !important;

          &:hover {
            background-color: black !important;
            opacity: 1 !important;
          }
        }
      }
    }
  }
}
</style>
