<script>

// 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 { easeInOutQuad, easeInOutQuart } from 'easing-utils';

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

export default {
  inject: ['canvasMap', 'matterEngine'],
  data() {
    return {
      // concernement: null,
      canvas: null,
      ctx: null,
      pos : {
        x: 0,
        y: 0
      },
      ray: 60,
      time: 0,
      salientPoints: [],
      scale: 1,
      anim: null,
      // matter
      body: null
    }
  },
  props: ['concernement', 'opened'],
  computed: {
    ...mapState(ConcernementsStore,['concernementsByID'])
  },
  created () {
    // console.log("ConcernementsMapItem concernement", this.canvasMap, this.matterEngine);
    this.entites = this.concernement.entites
    this.parsePoints()
    this.getSalientPoints()
  },
  mounted() {
    console.log('concernementItem mounted', typeof this.canvasMap.canvas);
    if (this.canvasMap) {
      this.initCanvasMap()
    }
  },
  watch: {
    // canvasMap (n, o) {
    //   console.log("concernementItem watch canvasMap", o, n);
    // }
    canvasMap: {
      handler (n, o){
        // console.log("concernementItem watch canvasMap.ctx", typeof this.canvas, o, n);
        if (!this.canvas) {
          this.initCanvasMap()
        }
      },
      deep: true
    },
    opened: {
      handler (n, o) {
        if(n){
          // opened
          this.anim = {
            init: this.scale,
            target: 5, //target scale
            start: Date.now(),
            duration: 1000 // ms 
          }
        }else{
          // closed
          this.anim = {
            init: this.scale,
            target: 1, //target scale
            start: Date.now(),
            duration: 1000 // ms 
          }
        }
        console.log(`watch opened ${this.concernement.id}`, n, o, this.anim);
      },
      deep: true
    }
  },
  methods: {
    initCanvasMap (){
      console.log('initCanvasMap');
      // record canvas and ctx for rendering (drawing)
      this.canvas = this.canvasMap.canvas
      this.ctx = this.canvasMap.ctx

      // define init position of the item
      this.pos.x = this.ray/2 + Math.random()*(this.canvas.width - this.ray)
      this.pos.y = this.ray/2 + Math.random()*(this.canvas.height - this.ray)
      
      // MATTER
      // create the matter body and add it to the engine
      if (!this.body) {
        // console.log('concernementItem creating body');

        // https://github.com/liabru/matter-attractors/issues/8        
        // https://github.com/liabru/matter-attractors/blob/master/index.js
        MatterAttractors.Attractors.gravityConstant = -1;
        this.body = Matter.Bodies.circle(this.pos.x, this.pos.y, this.ray, {
          frictionAir: 0,
          // mass: Math.pow(3, this.entites.length),
          mass: 10,
          restitution: 0.9,
          id: this.concernement.id,
          plugin: {
            attractors: [
              // there is a built in helper function for Newtonian gravity!
              // you can find out how it works in index.js
              MatterAttractors.Attractors.gravity
            ]
          }
        });
        let delta = 60;
        Matter.Body.setVelocity(this.body, {
            x: -delta + Math.random()*delta*2,
            y: -delta + Math.random()*delta*2
          });
        // console.log('concernementItem mass', this.body.mass);
        Matter.Composite.add(this.matterEngine.world, this.body);
        console.log('concernement body', this.body);
      }

      // // listen for animate event dispatched from parent
      // this.canvas.addEventListener('animate', this.animate)
      // listen for afterUpdate event from Matter.Engine object
      Matter.Events.on(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate)
    },
    parsePoints (){
      // converts data (menace/maintien, actuel/future, prise) into atcual position x,y
      for (let i = 0; i < this.entites.length; i++) {
        let entite = this.entites[i]
        // console.log('entite', entite);
        
        this.entites[i].display = {
          alpha: null,
          ray: null
        }
        // RAYON
        // https://stackoverflow.com/questions/5731863/mapping-a-numeric-range-onto-another
        // slope = (output_end - output_start) / (input_end - input_start)
        // output = output_start + slope * (input - input_start)
        // from range 0 -> 100 to range 0 -> this.ray
        let slope = this.ray / 100
        this.entites[i].display.ray = slope * (100 - entite.prise);

        // ANGLE
        // -90 <= mm <= 90
        if (entite.actuelfuture) {
          // future en haut : 180 <= a <= 360
          // from -90 -> 90 to range 180 -> 360
          this.entites[i].display.alpha = entite.menacemaintien + 270
        } else {
          // actuel: en bas : O <= a <= 180
          // from -90 -> 90 to range 180 -> 0
          this.entites[i].display.alpha = -1 * entite.menacemaintien + 90
        }

        // POSITION X Y (par rapport au centre de l'entite)
        this.entites[i].display.pos = {
          x: this.entites[i].display.ray * Math.cos(this.entites[i].display.alpha * (Math.PI/180)),
          y: this.entites[i].display.ray * Math.sin(this.entites[i].display.alpha * (Math.PI/180))
        }
      }
    },
    getSalientPoints () {
      // debugger
      // console.log(this.entites);
      let arc = 360/12;
      // loop through arcs
      for (let i = 0; i <= 360/arc; i++) {
        // loop through entities to find the farest on the arc
        let max_r = 0;
        let farest = null;
        for (let j = 0; j < this.entites.length; j++) {
          let entite = this.entites[j];
          if(arc*i <= entite.display.alpha && entite.display.alpha <= arc*i+arc) {
            // if entity is in arc
            if (entite.display.ray > max_r) {
              // if entity is farest from precedent one
              max_r = entite.display.ray;
              farest = entite;
            }
          }
        }
        if (farest) {
          this.salientPoints.push(farest.display)
        }
      }
      // console.log(`this.salientPoints ${this.concernement.id}`, this.salientPoints);
    },
    scaleBody(scale){
      // scale vertices
      Matter.Vertices.scale(this.body.parts[0].vertices, scale, scale);
      // update properties
      // this.body.parts[0].axes = Matter.Axes.fromVertices(this.body.parts[0].vertices);
      // update bounds
      // Matter.Bounds.update(this.body.parts[0].bounds, this.body.parts[0].vertices, this.body.velocity);
      this.body.circleRadius *= scale;
    },
    onAfterEngineUpdate (event) {
      
      if (this.anim) {
        let time = Date.now() - this.anim.start; // get time elapsed since anime start
        if (time <= this.anim.duration) {
          let ease = easeInOutQuart(time / this.anim.duration); // get the easing factor
          let scale = this.anim.init < this.anim.target 
            ? this.anim.init + this.anim.target * ease 
            : this.anim.init + (this.anim.target - this.anim.init) * ease; // get the current eased scale
          // // https://github.com/liabru/matter-js/issues/986#issuecomment-812488873
          // // revert to the original size (by reverting the previous scale)
          Matter.Body.scale(this.body, 1 / this.scale, 1 / this.scale)
          // this.scaleBody(1 / this.scale)
          // // then scale again to new scale
          Matter.Body.scale(this.body, scale, scale)
          // this.scaleBody(scale);
          // record new scale
          this.scale = scale;
        }else{
          this.anim = null;
        }
      
      }

    }
  },
  render() {
    // console.log('render()', this.ctx);

    if (!this.ctx) return;
    
    this.pos = this.body.position;
      
    // exterieur circle
    this.ctx.beginPath();
    this.ctx.lineWidth = 0.5;
    this.ctx.strokeStyle = this.concernement.opened ? "#ff0000" : "#888";
    this.ctx.arc(this.pos.x, this.pos.y, this.ray*this.scale, 0, 2 * Math.PI, false);
    this.ctx.stroke();

    // // interieur circle
    // this.ctx.beginPath();
    // this.ctx.lineWidth = 0.5;
    // this.ctx.strokeStyle = "#888";
    // this.ctx.arc(this.pos.x, this.pos.y, this.ray/2, 0, 2 * Math.PI, false);
    // this.ctx.stroke();

    // contours
    if (this.salientPoints.length > 3) {
      this.ctx.beginPath();
      this.ctx.lineWidth = 1;
      this.ctx.strokeStyle = "#000";
      this.ctx.fillStyle = "rgba(255,255,255,0.4)";
      this.ctx.moveTo(this.pos.x+this.salientPoints[0].pos.x*this.scale, this.pos.y+this.salientPoints[0].pos.y*this.scale)
      for (let j = 1; j < this.salientPoints.length; j++) {
        this.ctx.lineTo(this.pos.x+this.salientPoints[j].pos.x*this.scale, this.pos.y+this.salientPoints[j].pos.y*this.scale)
      }
      this.ctx.lineTo(this.pos.x+this.salientPoints[0].pos.x*this.scale, this.pos.y+this.salientPoints[0].pos.y*this.scale)
      this.ctx.fill();
      this.ctx.stroke();
    }

    // place all entities points
    for (let i = 0; i < this.entites.length; i++) {
      let entite = this.entites[i];
      // console.log('entite', entite);
      this.ctx.beginPath();
      this.ctx.arc(this.pos.x+entite.display.pos.x*this.scale, this.pos.y+entite.display.pos.y*this.scale, 2, 0, 2 * Math.PI, false);
      this.ctx.fillStyle = "#F00";
      this.ctx.fill();
    }


    // concernement id @center
    this.ctx.beginPath();
    // this.ctx.arc(this.pos.x, this.pos.y, 4, 0, 2 * Math.PI, false);
    this.ctx.fillStyle = "#000";
    this.ctx.fillText(this.concernement.id, this.pos.x, this.pos.y)
    this.ctx.fill();
    
    
  },
}

</script>
