<script>

// import { mapActions, mapState } from 'pinia'
import { computed } from 'vue'
import MapBackground from '@components/MapBackground.vue'

// https://brm.io/matter-js/docs/classes/Engine.html
// import {
//   Engine,
//   // Render,
//   // World,
//   Bodies,
//   // Body,
//   // Events,
//   Composite,
//   // Composites,
//   // Constraint,
//   // Vertices,
//   // Mouse,
//   // MouseConstraint,
//   // Query,
//   // Common
// } from "matter-js";
import Matter from "matter-js";

import MatterAttractors from "matter-attractors";
Matter.use(MatterAttractors);


import { mapState, mapActions } from 'pinia'
import { ConcernementsStore } from '@/stores/concernements'

import ConcernementMapPopup from '@components/ConcernementMapPopup.vue';

export default {
  data() {
    return {
      canvasMap: {
        canvas: null,
        ctx: null,
      },
      animateEvent: new Event('animate'),
      granim: null,
      // MATTER
      engine: null,
      world: null,
      // render: null,
      mouse: null,
      mapPopupData: null,
    }
  },
  provide() {
    // https://www.digitalocean.com/community/tutorials/vuejs-vue-html5-canvas
    return {
      // explicitly provide a computed property
      canvasMap: computed(() => this.canvasMap),
      matterEngine: computed(() => this.engine)
    }
  },
  computed: {
    ...mapState(ConcernementsStore,['concernements']),
    ...mapState(ConcernementsStore,['concernementsByID']),
    ...mapState(ConcernementsStore,['opened'])
  },
  created() {
    // MATTER
    // create an engine
    let engineOptions = {
      enableSleeping: true,
      timing: {
        //timestamp: 0.5,
        timeScale: 0.5
      }
    }
    this.engine = Matter.Engine.create(engineOptions);
    this.engine.gravity.scale = 0;
    this.world = this.engine.world;
  },
  mounted() {
    this.canvasMap.canvas = this.$refs['canvas-map'];
    this.canvasMap.ctx = this.canvasMap.canvas.getContext('2d');

    let canvas_w = this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
    let canvas_h = this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;

    // MATTER
    let wall_w = 100;
    Matter.Composite.add(this.world, [
        // walls
        Matter.Bodies.rectangle(canvas_w/2,        -wall_w/2,         canvas_w, wall_w,   { isStatic: true }),   // top
        Matter.Bodies.rectangle(canvas_w/2,        canvas_h+wall_w/2, canvas_w, wall_w,   { isStatic: true }),   // bottom
        Matter.Bodies.rectangle(-wall_w/2,         canvas_h/2,        wall_w,   canvas_h, { isStatic: true }),   // left
        Matter.Bodies.rectangle(canvas_w+wall_w/2, canvas_h/2,        wall_w,   canvas_h, { isStatic: true }),   // right
        // make the items never goes under menus
        Matter.Bodies.rectangle(550, canvas_h-15, 900, 30, { isStatic: true }),      // menu bottom
        Matter.Bodies.rectangle(550,          15, 900, 30, { isStatic: true })       // menu top
    ]);

    // add mouse control
    // https://github.com/liabru/matter-js/issues/491#issuecomment-331329404
    this.mouse = Matter.Mouse.create(this.canvasMap.canvas);
    this.canvasMap.canvas.addEventListener('mousemove', this.onMouseMove)
    this.canvasMap.canvas.addEventListener('click', this.onClick)

    this.animate()
  },
  methods: {
    ...mapActions(ConcernementsStore,['openCloseConcernements']),
    ...mapActions(ConcernementsStore,['resetConcernementOpened']),
    animate () {
      this.canvasMap.ctx.clearRect(0, 0, this.canvasMap.canvas.width, this.canvasMap.canvas.height)
      // this.canvasMap.canvas.dispatchEvent(this.animateEvent)
      Matter.Engine.update(this.engine, 1)
      window.requestAnimationFrame(this.animate);
    },
    onMouseMove (e) {
      // check item mouse over
      let query;
      if (this.opened) {
        // if a concernement is opened we query the opened concernement's parts (aka entitées bodies)
        const bodies = Matter.Composite.allBodies(this.world);
        for (let body of bodies) {
          if (body.item_type === "concernement" && body.id === this.opened.id) {
            query = Matter.Query.point(body.parts, this.mouse.position);
            break;    
          }
        }
      } else {
        // if no concernement opened we query concernements
        query = Matter.Query.point(this.world.bodies, this.mouse.position)
      }
      
      this.mapPopupData = null;
      if (query && query.length) {
        // if we have a results
        for (let body of query) {
          if (!this.opened // if no concernement is opened
            && body.item_type === "concernement" // if it is a concernement
            && typeof this.concernementsByID[body.id] !== "undefined"  // if the id exists
            && !this.concernementsByID[body.id].opened) { // if the concernement is not opened
              this.mapPopupData = {
                type: 'concernement',
                id: body.id
              };
          }
          if (body.item_type === "entite" // if it is an entite
            && this.opened // if a concernement is opened
            && typeof this.opened.entites_byid[body.id] !== "undefined") { // if the entity exists
              this.mapPopupData = {
                type: 'entite',
                id: body.id
              };
          }
        }
        // console.log(`this.mapPopupData type: ${this.mapPopupData.type}, id: ${this.mapPopupData.id}`);
      }
    },
    onClick (e) {
      console.log('onClick', this, e);
      // get the clicked element from matter
      // const query = Matter.Query.point(Matter.Composite.allBodies(this.world), this.mouse.position)
      let query;
      if (this.opened) {
        // if a concernement is opened we query the opened concernement's parts (aka entitées bodies)
        const bodies = Matter.Composite.allBodies(this.world);
        for (let body of bodies) {
          if (body.item_type === "concernement" && body.id === this.opened.id) {
            query = Matter.Query.point(body.parts, this.mouse.position);
            break;    
          }
        }
      } else {
        // if no concernement opened we query concernements
        query = Matter.Query.point(this.world.bodies, this.mouse.position)
      }
      // console.log(this.mouse.position);
      console.log('click query', query);
      
      // no concernement is yet opened, we deal concernements
      if (!this.opened) {
        if (query.length) {
          // open/close all concernements
          this.openCloseConcernements(query[0].id)
          // push route
          this.$router.push({name: 'concernement', params: {id: query[0].id}});
        }
      }

      // concernement is already opened, we deal with entités
      if (this.opened) {
        if (query.length) {
          let clickedEntityBodies = [];
          query.forEach(body => {
            // console.log('body id:', body.id);
            if (body.item_type === "entite") {
              clickedEntityBodies.push(body);
            }
          });
          if (clickedEntityBodies.length) {
            // we have clicked on an entite
            this.$router.push({name: 'concernement', params: {id: this.opened.id, eid: clickedEntityBodies[0].id}});
          } else {
            // otherwise we close the entite and come back to the concernement
            this.$router.push({name: 'concernement', params: {id: this.opened.id}});
          }
        } else {
          // if no concernement opened retrun to home (closing concernement contents opened)
          // and reset the opened state in concernement store
          this.resetConcernementOpened();
          this.$router.push({name: 'home'});
        }
      }
    }
  },
  beforeUpdate () {
  },
  components: {
    MapBackground,
    ConcernementMapPopup
  }
}

</script>

<template>
  <div id="map-backgrounds">
    <MapBackground />
  </div>
  <div id="map-matter">
    <canvas ref="canvas-engine"></canvas>
  </div>
  <div id="map-concernements">
    <canvas ref="canvas-map"></canvas>
    <slot></slot>
  </div>
  <nav id="map-nav">
    <ul>
      <li>
        <a href="#terraindevie">terrain de vie</a>
      </li>
      <li>
        <a href="#proximite">proximité</a>
      </li>
      <li>
        <a href="#superposition">superposition</a>
      </li>
      <li>
        <a href="#puissancedagir">puissance d'agir</a>
      </li>
      <li>
        <a href="#action">action</a>
      </li>
      <li>
        <a href="#doleancer">doléancer</a>
      </li>
    </ul>
  </nav>
  <ConcernementMapPopup
    v-if="mapPopupData"
    :infos="mapPopupData"
  />  
</template>

<style lang="css" scoped>

</style>
