<script>

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

// https://brm.io/matter-js/docs/classes/Engine.html
import Matter from "matter-js";

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

import paper from 'paper';

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

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

// import iconTerraindevie from "@/assets/icons/terraindevie.svg"
// import iconProximite from "@/assets/icons/proximite.svg"
// import iconSuperposition from "@/assets/icons/superposition.svg"
// import iconPuissanceagir from "@/assets/icons/puissancedagir.svg"
// import iconAction from "@/assets/icons/action_2.svg"
// import iconDoleancer from "@/assets/icons/doleancer.svg"

export default {
  data() {
    return {
      canvasMap: {
        canvas: null,
        ctx: null
      },
      animateEvent: new Event('animate'),
      granim: null,
      // MATTER
      engine: null,
      world: null,
      walls: null,
      // PAPERJS
      paper: null,
      //
      mapPopupData: null,
      //
      superpositions_constraints: []
    }
  },
  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,['map_mode',
                                    'concernements',
                                    'concernementsByID',
                                    'opened_concernement',
                                    'concernement_is_updating_nid',
                                    'opened_entite_id',
                                    'opened_recit',
                                    'allSuperpositions',
                                    // 'allSuperpositions_bycids',
                                    'allSuperpositions_clustered',
                                    'allMapItems_byid'
                                  ]),
    ...mapState(CommonStore,['map_item_ray',
                             'hover_elmt',
                             'paper_symbol_definitions'])
  },
  created() {
    // MATTER
    // create an engine
    let engineOptions = {
      enableSleeping: true,
      timing: {
        //timestamp: 0.5,
        timeScale: 0.5
      },
      // constraintIterations: 20,
      // positionIterations: 20,
      // velocityIterations: 20
    }
    this.engine = Matter.Engine.create(engineOptions);
    this.engine.gravity.scale = 0;
    this.world = this.engine.world;


    // listen for afterUpdate event from Matter.Engine object
    Matter.Events.on(this.engine, "beforeUpdate", this.onBeforeEngineUpdate);
    Matter.Events.on(this.engine, "afterUpdate", this.onAfterEngineUpdate);
  },
  mounted() {
    console.log('map mounted');

    // update the cartouch width reference
    this.setOriginalCartoucheWidth(this.getCartouchWidth());

    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;
    console.log(`canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);


    // PAPER
    this.paper = paper.setup(this.canvasMap.canvas);
    // this.paper.view.viewSize = new paper.Size(canvas_w, canvas_h);
    // this resizing is needed for display with pixel ratio more than 1 (retina)
    this.canvasMap.canvas.setAttribute('width', canvas_w);
    this.canvasMap.canvas.setAttribute('height', canvas_h);

    // symbol defintions
    this.initPaperSymbols();

    // use the paper.view click to get back if no items is clicked
    this.paper.view.onClick = function(event) {
      // console.log("view onClick", this, event.target);
      if(event.target._id === "paper-view-0") {
        // // unfocus any active element to trigger recording if needed
        // document.activeElement.blur();
        // // setTimeout to let time for editable fields to focus out and record changes
        // setTimeout(() => {
        //   this.resetConcernementOpened();
        //   this.$router.push({
        //     name: 'home',
        //     hash: `#${this.map_mode}`
        //   });
        // }, 1);
        this.closeConcernement();
      }
    }.bind(this);

    // use the paper.view mousemouve to removed mappopup
    this.paper.view.onMouseMove = function(event) {
      // console.log("view onMouseMove", event.target);
      if(event.target._id === "paper-view-0") {
        this.setHoverElmt(null);
      }
    }.bind(this);

    // MATTER
    this.buildMatterWalls();

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

    window.addEventListener("resize", this.onWindowResize.bind(this));

    this.animate()
  },
  watch: {
    hover_elmt: {
      handler (n, o) {
        // console.log(`watch hover_elmt map: o, n`, o, n);
        // over highlight effect on paper items
        if (n && n.paper_id) {
          let nitem = paper.project.getItem({id: n.paper_id});
          // console.log('watch hover_element nitem', nitem.definition);
          if (!nitem.is_symbol_instance) { // not symbol instance
            nitem.bringToFront();
            if (nitem.strokeColor) {
              nitem.data.prevStrokeColor = nitem.strokeColor.toCSS(true);
              nitem.strokeColor = "#01ffe2";          
            } else {
              nitem.data.prevFillColor = nitem.fillColor.toCSS(true);
              nitem.fillColor = "#01ffe2";
            }
            
          } else { // is a symbol instanceof, then swap
            // console.log(`symbol instance n.type:${n.type}, nitem`, nitem);
            switch (n.type) {
              case 'entite':
                nitem.definition = this.paper_symbol_definitions.entite_hover;
                break;
              case 'besoin':
                nitem.definition = this.paper_symbol_definitions.besoin_hover;
                break;
              case 'reponse':
                nitem.definition = this.paper_symbol_definitions.reponse_hover;
                break;
              case 'entite_action':
                nitem.definition = this.paper_symbol_definitions.entite_action_hover;
                break;
            }
          }
        }

        if (o && o.paper_id && (!n || o.paper_id !== n.paper_id)) {
          let oitem = paper.project.getItem({id: o.paper_id})
          if (oitem) {
            // console.log('watch hover_element oitem', oitem);
            if (!oitem.is_symbol_instance) { // not symbol instance
              if (oitem.data.prevStrokeColor) {
                oitem.strokeColor = oitem.data.prevStrokeColor;
              } else {
                oitem.fillColor = oitem.data.prevFillColor;
              }            
            } else { // is a symbol instanceof, then swap
              // console.log(`symbol instance o.type:${o.type}, oitem`, oitem);
              switch (o.type) {
                case 'entite':
                  // console.log('this.opened_entite_id', parseInt(this.opened_entite_id), 'oitem.item_id', oitem.item_id);
                  if (!this.opened_entite_id || parseInt(this.opened_entite_id) !== oitem.item_id) {
                    oitem.definition = this.paper_symbol_definitions.entite;
                  }
                  break;
                case 'besoin':
                  oitem.definition = this.paper_symbol_definitions.besoin;
                  break;
                case 'reponse':
                  oitem.definition = this.paper_symbol_definitions.reponse;
                  break;
                case 'entite_action':
                  if (!this.opened_entite_id || parseInt(this.opened_entite_id) !== oitem.item_id) {
                    oitem.definition = this.paper_symbol_definitions.entite_action;
                  }
                  break;
              }
            }
          }

        }
      },
      deep: true
    },
    map_mode: {
      handler (n, o) {
        console.log('concernementMap watch map_mode o n', o, n);
        if (n === 'superposition') { // && !this.opened_concernement
          // create constraints
          this.setSuperpositionsMatterConstraints();
        }else{
          // destroy constraints
          this.clearSuperpositionsMatterConstraints();
        }
      },
      deep: true
    },
    opened_concernement: {
      handler (n, o) {
        console.log('concernementMap watch opened_concernement o n', o, n);
        // if (n && this.map_mode === 'superposition') {
        //   this.clearSuperpositionsMatterConstraints();
        // }
        // if(o && !n){
        //   this.setSuperpositionsMatterConstraints();
        // }
      },
      deep: true
    },
    allSuperpositions: {
      handler (n, o) {
        console.log('concernementMap watch allSuperpositions', o, n);
        if (this.map_mode === "superposition" && n && n.length) {
          // create constraints with a delay (watch is needed for first page load)
          window.setTimeout(this.setSuperpositionsMatterConstraints, 200);
        }
        // else{
        //   // destroy constraints
        //   this.clearSuperpositionsMatterConstraints();
        // }
      },
      deep: true
    },
    // opened_concernement: {
    //   handler (n, o) {
    //     console.log('map opened_concernement', this.opened_concernement);
    //     if (this.map_mode === 'superposition' && n) {
    //       this.resetSuperpositionsMatterConstraints();
    //     }
    //   }, 
    //   deep: true
    // }
  },
  methods: {
    ...mapActions(ConcernementsStore,['setMapMode',
                                      'resetConcernementOpened']),
    ...mapActions(CommonStore,['addPaperSymbolDefinition',
                               'setHoverElmt',
                               'updateMapItemRay',
                               'setOriginalCartoucheWidth']),
    animate () {
      // if (document.hasFocus()) {
        Matter.Engine.update(this.engine, 1);
      // }
      window.requestAnimationFrame(this.animate);
    },
    buildMatterWalls(){
      console.log('buildMatterWalls');
      // remove old walls if exists
      let oldWallsBody = Matter.Composite.get(this.world, 'walls', 'body');
      if (oldWallsBody) {
        console.log('buildMatterWalls oldWallsBody', oldWallsBody);  
        Matter.Composite.remove(this.world, oldWallsBody);
      }
      console.log('buildMatterWalls oldWallsBody after remove', Matter.Composite.get(this.world, 'walls', 'body'));

      // create walls
      let canvas_w = this.canvasMap.canvas.width;
      let canvas_h = this.canvasMap.canvas.height;
      console.log(`buildMatterWalls canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
      let length = 10000; // set a length long enought that we don't have to redimmension it when window resize
      let thickness = 1000;
      let pad = 1;
      let wallsParts = [
        // walls
        // Matter.Bodies.rectangle(x, y, width, height, [options])
        Matter.Bodies.rectangle(canvas_w/2,        -thickness/2 +pad,         length, thickness,   { label: 'top_wall'}),   // top
        Matter.Bodies.rectangle(canvas_w/2,        canvas_h+thickness/2 -pad, length, thickness,   { label: 'bottom_wall'}),   // bottom
        Matter.Bodies.rectangle(-thickness/2 +pad,         canvas_h/2,        thickness,   length, { label: 'left_wall'}),   // left
        Matter.Bodies.rectangle(canvas_w+thickness/2 -pad, canvas_h/2,        thickness,   length, { label: 'right_wall'}),   // right
        // make the items never goes under menus
        // Matter.Bodies.rectangle(500,               25,                1000,      50,       { label: 'menutop_wall'}),  // menu top
        // Matter.Bodies.rectangle(500,               canvas_h-15,       1000,      30,       { label: 'menubottom_wall'})   // menu bottom
      ];
      this.walls = Matter.Body.create({
        parts: wallsParts,
        id: 'walls',
        isStatic: true
      });
      Matter.Composite.add(this.world, this.walls);
      console.log('buildMatterWalls this.walls', this.walls);
    },
    updateMatterWalls(){
      let canvas_w = this.canvasMap.canvas.width;
      let canvas_h = this.canvasMap.canvas.height;
      console.log(`buildMatterWalls canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
      let thickness = 1000;
      let pad = 10;

      this.walls.parts.forEach((p, i) =>{
        // console.log('p.label', p.label);
        let pos = false;
        switch (p.label) {
          case 'top_wall':
            pos = Matter.Vector.create(canvas_w/2, -thickness/2 +pad)
            break;
          case 'bottom_wall':
            pos = Matter.Vector.create(canvas_w/2, canvas_h+thickness/2 -pad)
            break;
          case 'left_wall':
            pos = Matter.Vector.create(-thickness/2 +pad, canvas_h/2)
            break;
          case 'right_wall':
            pos = Matter.Vector.create(canvas_w+thickness/2 -pad, canvas_h/2)
            break;
          case 'menutop_wall':
            pos = Matter.Vector.create(500, 25)
            break;
          case 'menubottom_wall':
            pos = Matter.Vector.create(500, canvas_h-15)
            break;
        }
        if(pos){
          Matter.Body.setPosition(p, pos);
        }
      })
    },
    onWindowResize(e){
      // console.log('onWindowResize', e);
      // get the new size
      let canvas_w = this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
      let canvas_h = this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;
      console.log(`canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);

      // apply to paper env
      // paper.view.viewSize.width = canvas_w;
      // paper.view.viewSize.height = canvas_h;
      this.paper.view.viewSize = new paper.Size(canvas_w, canvas_h);
      // this.canvasMap.canvas.setAttribute('width', canvas_w);
      // this.canvasMap.canvas.setAttribute('height', canvas_h);

      // apply to matter env
      // this.buildMatterWalls();
      this.updateMatterWalls();


      // resize the base item ray, this will trigger all the map_items to resize in nextTick()
      this.updateMapItemRay();

      // rebuild all the paper symbols with new ray
      this.initPaperSymbols(true)

      // update the cartouch width reference
      this.setOriginalCartoucheWidth(this.getCartouchWidth());


    },
    getCartouchWidth(){
      let ww = window.clientWidth;
      if (ww > 1500) {
        return 450;
      } else if (ww > 880) {
        return 400;
      } else {
        return 350;
      }
    },
    initPaperSymbols(update){
      this.addPaperSymbolDefinition('boussole_bg', this.setPaperBoussoleBGSymbol());
      this.addPaperSymbolDefinition('puissanceagir_bg', this.setPaperPuissanceagirBGSymbol());
      // this.addPaperSymbolDefinition('puissanceagir_icon', this.setPaperPuissanceagirICONSymbol());
      this.addPaperSymbolDefinition('doleance_bg', this.setPaperDoleanceBGSymbol());
      // this.addPaperSymbolDefinition('doleance_icon', this.setPaperDoleanceICONSymbol());
      if (!update) {
        this.addPaperSymbolDefinition('entite', this.setPaperEntiteSymbol());
        this.addPaperSymbolDefinition('entite_hover', this.setPaperEntiteHoverSymbol());
        this.addPaperSymbolDefinition('entite_inactive', this.setPaperInactiveEntiteSymbol());
        this.addPaperSymbolDefinition('entite_inactive_hover', this.setPaperInactiveEntiteHoverSymbol());
        this.addPaperSymbolDefinition('entite_hidden', this.setPaperHiddenEntiteSymbol());
        this.addPaperSymbolDefinition('entite_action_icon', this.setPaperEntiteActionIconSymbol());
        this.addPaperSymbolDefinition('entite_action', this.setPaperEntiteActionSymbol());
        this.addPaperSymbolDefinition('entite_action_hover', this.setPaperEntiteActionHoverSymbol());
        this.addPaperSymbolDefinition('besoin', this.setPaperBesoinSymbol());
        this.addPaperSymbolDefinition('besoin_hover', this.setPaperBesoinHoverSymbol());
        this.addPaperSymbolDefinition('reponse', this.setPaperReponseSymbol());
        this.addPaperSymbolDefinition('reponse_hover', this.setPaperReponseHoverSymbol());
      }
    },
    setPaperBoussoleBGSymbol(){
      // BOUSSOLE
      let children = [];
      let ray = this.map_item_ray;
      let pos = {x:0, y:0};

      // big invisible global exterior circle to keep center aligned
      children.push(new paper.Path.Circle({
        center: [0, 0],
        radius: ray*3,
        style: {
          strokeColor: 'rgba(255,255,255,0)',
          strokeWidth: 0.5
        }
      }));

      // cercles
      // for (let i = 1; i < 9; i++) {
      //   let sw = i === 4 || i === 8 ? 0.25 : 0.1; // width
      //   let da = i === 4 || i === 8 ? null : [5,5]; // dash array
      //   if (!da) { // draw only 2 main non-dashed circles
      //     children.push(new paper.Path.Circle({
      //       center: [pos.x, pos.y],
      //       radius: ray/8*i,
      //       strokeColor: '#fff',
      //       strokeWidth: sw,
      //       dashArray: da
      //     }));
      //   }
      // }

      // cercle exterieur
      let ext_circle_factor = 0.915; // be eware that concernement map item also use this factor
      children.push(new paper.Path.Circle({
        center: [pos.x, pos.y],
        radius: ray*ext_circle_factor,
        strokeColor: '#fff',
        strokeWidth: 0.25
      }));
      // cercle interieur
      children.push(new paper.Path.Circle({
        center: [pos.x, pos.y],
        radius: ray*0.51,
        strokeColor: '#fff',
        strokeWidth: 0.25
      }));

      // axes
      // vertical
      children.push(new paper.Path.Line({
        from: [pos.x, pos.y - ray*ext_circle_factor],
        to: [pos.x, pos.y + ray*ext_circle_factor],
        strokeColor: '#fff',
        strokeWidth: 0.25
      }));
      // horizontal
      children.push(new paper.Path.Line({
        from: [pos.x - ray*ext_circle_factor, pos.y],
        to: [pos.x + ray*ext_circle_factor, pos.y],
        strokeColor: '#fff',
        strokeWidth: 0.25
      }))
      
      // fleches
      // haute
      children.push(new paper.Path({
        segments: [
          [pos.x - 8, pos.y - ray*ext_circle_factor + 8],
          [pos.x, pos.y - ray*ext_circle_factor],
          [pos.x + 8, pos.y - ray*ext_circle_factor + 8],
        ],
        strokeWidth: 0.25,
        strokeColor: '#fff',
      }));
      // milieu
      children.push(new paper.Path({
        segments: [
        [pos.x - 8, pos.y + 8],
        [pos.x, pos.y],
        [pos.x + 8, pos.y + 8],
        ],
        strokeWidth: 0.25,
        strokeColor: '#fff',
      }));


      // MOINS - PLUS
      // PLUS
      // horizontal
      children.push(new paper.Path.Line({
        from: [pos.x + ray - 5, pos.y - ray],
        to: [pos.x + ray + 5, pos.y - ray],
        strokeWidth: 2,
        strokeColor: '#fff',
      }))
      // vertical
      children.push(new paper.Path.Line({
        from: [pos.x + ray, pos.y - ray - 5],
        to: [pos.x + ray, pos.y - ray + 5],
        strokeWidth: 2,
        strokeColor: '#fff',
      }))
      
      // MOINS
      // horizontal
      children.push(new paper.Path.Line({
        from: [pos.x - ray - 5, pos.y - ray],
        to: [pos.x - ray + 5, pos.y - ray],
        strokeWidth: 2,
        strokeColor: '#fff',
      }))

      let fontsize = 3;
      let fontFamily = "public_sans";
      
      children.push(new paper.PointText({
        point: [pos.x + 4.5, pos.y - ray],
        content: `entités qui menacent \u2194 entités qui maintiennent`,
        fontSize: fontsize,
        fontFamily: fontFamily,
        justification: 'center',
        fillColor: '#000',
      }))

      children.push(new paper.PointText({
        point: [pos.x - ray, pos.y + 1],
        content: "axe d'intensité",
        fontSize: fontsize,
        fontFamily: fontFamily,
        justification: 'right',
        fillColor: '#000',
      }))

      children.push(new paper.PointText({
        point: [pos.x + ray, pos.y - 3],
        content: "situation future\n\u2195\nsituation actuelle",
        fontSize: fontsize,
        fontFamily: fontFamily,
        justification: 'left',
        fillColor: '#000',
      }))


      let t1 = new paper.PointText({
        point: [pos.x - ray/8*2.54, pos.y - ray/8*2.54],
        content: "avec prise",
        fontSize: fontsize,
        fontFamily: fontFamily,
        justification: 'center',
        fillColor: '#000',
      })
      t1.rotate(-45)
      children.push(t1)

      let t2 = new paper.PointText({
        point: [pos.x - ray/8*3.1, pos.y - ray/8*3.1],
        content: "sans prise",
        fontSize: fontsize,
        fontFamily: fontFamily,
        justification: 'center',
        fillColor: '#000',
      })
      t2.rotate(-45)
      children.push(t2)


      return new paper.Group({
        children: children,
        pivot: new paper.Point(pos),
        name: 'boussole_bg',
        // locked: true,
      });

    },
    setPaperPuissanceagirBGSymbol(){
      let children = [];
      let ray = this.map_item_ray;
      let pos = {x:0,y:0};

      // cercles interieur
      for (let i = 1; i < 6; i++) {
        children.push(new paper.Path.Circle({
          center: [pos.x, pos.y],
          radius: (ray/5)*i,
          strokeWidth: 0.25
        }));
      }

      // rayons
      for (let j = 0; j < 16; j++) {
        let a  = (360 / 16) * j;
        
        let ext_x = Math.cos(a*(Math.PI/180)) * ray;
        let ext_y = Math.sin(a*(Math.PI/180)) * ray;
        let int_x = Math.cos(a*(Math.PI/180)) * 2;
        let int_y = Math.sin(a*(Math.PI/180)) * 2;

        children.push(new paper.Path.Line({
          from: [pos.x + ext_x, pos.y + ext_y],
          to: [pos.x + int_x, pos.y + int_y],
          strokeWidth: 0.25,
          dashArray: [0.5,1]
        }))
      }
      
      // cercle exterieur
      children.push(new paper.Path.Circle({
        center: [pos.x, pos.y],
        radius: ray,
        strokeWidth: 0.5,
        fillColor: `rgba(255,255,255,0.6)`
      }));


      return new paper.Group({
        children: children,
        pivot: new paper.Point(pos),
        name: 'puissanceagir_bg',
        // locked: true,
        style: {
          strokeColor: '#fff'
        }
      });
    },
    // setPaperPuissanceagirICONSymbol(){
    //   let children = [];

    //   let svgIcon = paper.project.importSVG(iconPuissanceagir);
    //   children.push(svgIcon);
    //   svgIcon.position = this.pos;
      
    //   return new paper.Group({
    //     children: children,
    //     pivot: new paper.Point(this.pos),
    //     name: 'puissanceagir_icon',
    //     locked: true,
    //     style: {
    //       strokeColor: '#000',
    //       strokeWidth: 0.75,
    //       fillColor: null
    //     }
    //   });
    // },
    setPaperDoleanceBGSymbol(){
      let ray = this.map_item_ray;
      let pos = {x:0,y:0};
      var r = ray * 0.8;  // ray
      var dr = r/2;                         // demi ray
      var pcr = 3;               // petits cercle rayon

      // https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie#/media/Fichier:Unit_circle_angles_color.svg
      // https://fr.wikipedia.org/wiki/Identit%C3%A9_trigonom%C3%A9trique_pythagoricienne#Preuve_utilisant_le_cercle_unit%C3%A9
      // radians = degrees * (pi/180)
      // degrees = radians * (180/pi)
      // Points for 45° axes
      let m = Math.sin(45*(Math.PI/180)) * r;   // x = y for rayon
      let n = Math.sin(45*(Math.PI/180)) * r/2; // x = y for demi rayon
      // console.log('m', m);

      // points for legende arcs
      var lar = r*1.1;                       // legendes arcs rayon
      let o = Math.cos(22.5*(Math.PI/180)) * lar; // x @ 22.5° for legende arc rayon
      let p = Math.sin(22.5*(Math.PI/180)) * lar; // y @ 22.5° for legende arc rayon
      let q = Math.sin(45*(Math.PI/180)) * lar;   // x = y  @ 45° for legende arc rayon

      var ltr = lar + 4;                       // legendes texts rayon
      let o_t = Math.cos(22.5*(Math.PI/180)) * ltr; // x @ 22.5° for legende text rayon
      let p_t = Math.sin(22.5*(Math.PI/180)) * ltr; // y @ 22.5° for legende text rayon
      let q_t = Math.sin(45*(Math.PI/180)) * ltr;   // x = y  @ 45° for legende text rayon

      let style = {strokeColor: '#fff', strokeWidth: 0.25}
      let felchesstyle = {strokeColor: '#fff', strokeWidth: 0.5}
      let legende_style = {strokeColor: '#000', strokeWidth: 0.25}
      let fontsize = 3;
      let fontFamily = "public_sans";

      let children = [

        // big global exterior circle to keep center aligned
        new paper.Path.Circle({
          center: [0, 0],
          radius: r*3,
          style: {
            strokeColor: 'rgba(255,255,255,0)',
            strokeWidth: 0.5
          }
        }),
        //
        // ARCS EXTERIEURS
        // haut gauche
        new paper.Path.Arc({
          from: [- r, -pcr],
          through: [- m, -m],
          to: [ -pcr, -r],
          style: style
        }),
        // haut droite
        new paper.Path.Arc({
          from: [pcr, -r],
          through: [m, -m],
          to: [r, -pcr],
          style: style
        }),
        // bas droite
        new paper.Path.Arc({
          from: [r, pcr],
          through: [m, m],
          to: [pcr, r],
          style: style
        }),
        // bas gauche
        new paper.Path.Arc({
          from: [-pcr, r],
          through: [-m, m],
          to: [-r, pcr],
          style: style
        }),
        //
        // cercle interieur
        new paper.Path.Circle({
          center: [0, 0],
          radius: dr,
          style: style
        }),
        //
        // petit cercles
        new paper.Path.Circle({
          center: [0, -r],
          radius: pcr,
          style: style
        }),
        new paper.Path.Circle({
          center: [0, r],
          radius: pcr,
          style: {...style, ...{fillColor: 'rgba(255,255,255,0.9)'}},
        }),
        new paper.Path.Circle({
          center: [r, 0],
          radius: pcr,
          style: style
        }),
        new paper.Path.Circle({
          center: [-r, 0],
          radius: pcr,
          style: style
        }),
        //
        // AXES
        // vertical haut
        new paper.Path.Line({
          from: [0, -r + pcr],
          to: [0, -dr],
          style: style
        }),
        // vertical bas
        new paper.Path.Line({
          from: [0, r - pcr],
          to: [0, dr],
          style: style
        }),
        // horizontal gauche
        new paper.Path.Line({
          from: [-r + pcr, 0],
          to: [-dr, 0],
          style: style
        }),
        // horizontal droite
        new paper.Path.Line({
          from: [r - pcr, 0],
          to: [dr, 0],
          style: style
        }),
        //
        // DIAGONALES
        // bas droite
        new paper.Path.Line({
          from: [m, m],
          to: [n, n],
          style: style
        }),
        // bas gauche
        new paper.Path.Line({
          from: [-m, m],
          to: [-n, n],
          style: style
        }),
        // fleches
        // haut
        new paper.Path({
          segments: [
            [-4, -dr*1.5 - 4],
            [0, -dr*1.5],
            [-4, -dr*1.5 + 4]
          ],
          style: felchesstyle
        }),
        // bas
        new paper.Path({
          segments: [
            [4, dr*1.5 - 4],
            [0, dr*1.5],
            [4, dr*1.5 + 4]
          ],
          style: felchesstyle
        }),
        // gauche
        new paper.Path({
          segments: [
            [-dr*1.5 - 4, 4],
            [-dr*1.5, 0],
            [-dr*1.5 + 4, 4]
          ],
          style: felchesstyle
        }),
        // droite
        new paper.Path({
          segments: [
            [dr*1.5 - 4, -4],
            [dr*1.5, 0],
            [dr*1.5 + 4, -4]
          ],
          style: felchesstyle
        }),
        //
        // LEGENDES
        //
        // arc bas gauche 1
        new paper.Path.Arc({
          from: [-pcr, lar],
          through: [-p, o],
          to: [-q + pcr/2, q + pcr/2],
          style: legende_style
        }),
        // tiret
        new paper.Path.Line({
          from: [-p, o],
          to: [-p_t, o_t],
          style: legende_style
        }),
        //text
        new paper.PointText({
          point: [-p_t - 1, o_t],
          content: "2. Enquête menée\nsur le terrain de vie",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'right'
        }),
        // arc bas gauche 2
        new paper.Path.Arc({
          from: [-q - pcr/2, q - pcr/2],
          through: [-o, p],
          to: [-lar, pcr],
          style: legende_style
        }),
        // tiret
        new paper.Path.Line({
          from: [-o, p],
          to: [-o_t, p_t],
          style: legende_style
        }),
        // texte
        new paper.PointText({
          point: [-o_t - 1, p_t],
          content: "3. Construction de groupes d'intérets\navec qui composer la doléance",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'right'
        }),
        // arc haut gauche
        new paper.Path.Arc({
          from: [-lar, -pcr],
          through: [-q, -q],
          to: [-pcr, -lar],
          style: legende_style
        }),
        // tiret
        new paper.Path.Line({
          from: [-q, -q],
          to: [-q_t, -q_t],
          style: legende_style
        }),
        // texte
        new paper.PointText({
          point: [-q_t - 1, -q_t],
          content: "5. Réception et traitement\nde la doléance",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'right'
        }),
        // arc haut droite
        new paper.Path.Arc({
          from: [pcr, -lar],
          through: [q, -q],
          to: [lar, -pcr],
          style: legende_style
        }),
        // tiret
        new paper.Path.Line({
          from: [q, -q],
          to: [q_t, -q_t],
          style: legende_style
        }),
        // texte
        new paper.PointText({
          point: [q_t + 1, -q_t],
          content: "7. Mise-en-œuvre\nde la décision",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'left'
        }),
        // arc bas droite 1
        new paper.Path.Arc({
          from: [lar, pcr],
          through: [o, p],
          to: [q + pcr/2, q - pcr/2],
          style: legende_style
        }),
        // tiret
        new paper.Path.Line({
          from: [o, p],
          to: [o_t, p_t],
          style: legende_style
        }),
        // texte
        new paper.PointText({
          point: [o_t + 1, p_t],
          content: "9. Réception et application\nde la décision",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'left'
        }),
        // arc bas droite 2
        new paper.Path.Arc({
          from: [q - pcr/2, q + pcr/2],
          through: [p, o],
          to: [pcr, lar],
          style: legende_style
        }),
        // tiret
        new paper.Path.Line({
          from: [p, o],
          to: [p_t, o_t],
          style: legende_style
        }),
        // texte
        new paper.PointText({
          point: [p_t + 1, o_t],
          content: "10. Réussite / échec / reprise\ndu cercle politique",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'left'
        }),
        //
        // Points Cardinaux
        //
        // haut
        new paper.Path.Circle({
          center: [0, -r],
          radius: 0.5,
          style: {
            fillColor: '#000'
          }
        }),
        new paper.Path.Line({
          from: [0, -r],
          to: [0, -r - 9],
          style: legende_style
        }),
        new paper.PointText({
          point: [0, -r - 11],
          content: "6. Décision",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'center'
        }),
        // bas
        new paper.Path.Circle({
          center: [0, r],
          radius: 0.5,
          style: {
            fillColor: '#000'
          }
        }),
        new paper.Path.Line({
          from: [0, r],
          to: [0, r + 9],
          style: legende_style
        }),
        new paper.PointText({
          point: [0, r + 14],
          content: "1. Début du cercle\nLe problème\n(injustice, indignation, plainte...)",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'center'
        }),
        // droite
        new paper.Path.Circle({
          center: [r, 0],
          radius: 0.5,
          style: {
            fillColor: '#000'
          }
        }),
        new paper.Path.Line({
          from: [r, 0],
          to: [r + 8, 0],
          style: legende_style
        }),
        new paper.PointText({
          point: [r + 10, -0.5],
          content: "8. Adresse de la décision\nà appliquer",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'left'
        }),
        // gauche
        new paper.Path.Circle({
          center: [-r, 0],
          radius: 0.5,
          style: {
            fillColor: '#000'
          }
        }),
        new paper.Path.Line({
          from: [-r, 0],
          to: [-r - 8, 0],
          style: legende_style
        }),
        new paper.PointText({
          point: [-r - 10, 0.4],
          content: "4. Adresse de la doléance",
          fontSize: fontsize,
          fontFamily: fontFamily,
          justification: 'right'
        }),
      ];

      return new paper.Group({
        children: children,
        pivot: new paper.Point(pos),
        name: 'doleance_bg',
        // locked: true
      });
    },
    // setPaperDoleanceICONSymbol(){
    //   let children = [];

    //   let svgIcon = paper.project.importSVG(iconDoleancer);
    //   children.push(svgIcon);
    //   svgIcon.position = this.pos;

    //   return new paper.Group({
    //     children: children,
    //     pivot: new paper.Point(this.pos),
    //     name: 'doleance_icon',
    //     locked: true,
    //     style: {
    //       strokeColor: '#000',
    //       strokeWidth: 0.75,
    //       fillColor: null
    //     }
    //   });
    // },
    setPaperEntiteSymbol(){
      return new paper.Path.Circle({
        pivot: new paper.Point({x:0,y:0}),
        center: [0,0],
        radius: 0.5, //0.3
        fillColor: '#000',
        strokeColor: 'rgba(255,255,255,0.05)',
        strokeWidth:2
      })
    },
    setPaperEntiteHoverSymbol(){
      return new paper.Path.Circle({
        pivot: new paper.Point({x:0,y:0}),
        center: [0,0],
        radius: 0.5,
        fillColor: '#01ffe2',
        strokeColor: 'rgba(255,255,255,0.05)',
        strokeWidth:2
      })
    },
    setPaperHiddenEntiteSymbol(){
      return new paper.Path.Circle({
        pivot: new paper.Point({x:0,y:0}),
        center: [0,0],
        radius: 0.7, //0.3
        fillColor: '#fff',
        strokeColor: 'rgba(255,255,255,0.05)',
        strokeWidth:2
      })
    },
    setPaperInactiveEntiteSymbol(){
      return new paper.Path.Circle({
        pivot: new paper.Point({x:0,y:0}),
        center: [0,0],
        radius: 0.5, //0.3
        fillColor: '#F00',
        strokeColor: 'rgba(255,0,0,0.05)',
        strokeWidth:2
      })
    },
    setPaperInactiveEntiteHoverSymbol(){
      // let svgIcon = paper.project.importSVG(iconAction);
      // svgIcon.strokeColor = '#01ffe2';
      // svgIcon.strokeWidth = 0.25;
      // svgIcon.scale(0.15);
      // svgIcon.fillColor = null;
      // svgIcon.position = {x:0, y:0};

      // let circle = new paper.Path.Circle({
      //   radius: 3,
      //   fillColor: 'rgba(255,255,255,0.05)'
      // })

      // return new paper.Group({
      //   children: [circle, svgIcon],
      //   name: 'action_icon'
      // });
      let children = [];
      let ray = 0.7; //this.map_item_ray;
      // let pos = {x:0, y:0};
      // let strokewidth = 0.4;

      // children.push(new paper.Path.Line({
      //   from: [- ray, ray],
      //   to: [ray, - ray],
      //   strokeColor: '#01ffe2',
      //   strokeWidth: strokewidth
      // })); 

      // children.push(new paper.Path.Line({
      //   from: [ray, ray],
      //   to: [- ray, - ray],
      //   strokeColor: '#01ffe2',
      //   strokeWidth: strokewidth
      // })); 

      children.push(new paper.Path.Circle({
        radius: ray/2,
        fillColor: '#F00'
      }))

      children.push(new paper.Path.Circle({
        radius: ray * 1.2,
        strokeColor: '#01ffe2',
        strokeWidth: 0.2,
        fillColor: 'rgba(0,0,0,0)'
      }))

      children.push(new paper.Path.Circle({
        radius: ray,
        fillColor: 'rgba(255,255,255,0.01)'
      }))

      return new paper.Group({
        children: children,
        name: 'action_icon'
      });
    },
    setPaperEntiteActionIconSymbol(){
      // let svgIcon = paper.project.importSVG(iconAction);
      // svgIcon.strokeWidth = 0.8;
      // svgIcon.scale(0.6);
      // svgIcon.strokeColor = '#000';
      // svgIcon.fillColor = null;
      // svgIcon.position = {x:0, y:0};

      let children = [];
      let ray = 2; //this.map_item_ray;
      let pos = {x:0, y:0};

      children.push(new paper.Path.Line({
        from: [- ray, ray],
        to: [ray, - ray],
        strokeColor: '#000',
        strokeWidth: 1.1
      })); 

      children.push(new paper.Path.Line({
        from: [ray, ray],
        to: [- ray, - ray],
        strokeColor: '#000',
        strokeWidth: 1.1
      })); 

      return new paper.Group({
        children: children,
        name: 'action_icon'
      });
    },
    setPaperEntiteActionSymbol(){
      // let svgIcon = paper.project.importSVG(iconAction);
      // svgIcon.strokeWidth = 0.25;
      // svgIcon.scale(0.15);
      // svgIcon.strokeColor = '#000';
      // svgIcon.fillColor = null;
      // svgIcon.position = {x:0, y:0};
      let children = [];
      let ray = 1; //this.map_item_ray;
      // let pos = {x:0, y:0};

      // children.push(new paper.Path.Line({
      //   from: [- ray, ray],
      //   to: [ray, - ray],
      //   strokeColor: '#000',
      //   strokeWidth: strokewidth
      // })); 

      // children.push(new paper.Path.Line({
      //   from: [ray, ray],
      //   to: [- ray, - ray],
      //   strokeColor: '#000',
      //   strokeWidth: strokewidth
      // })); 


      children.push(new paper.Path.Circle({
        radius: ray/2,
        fillColor: 'rgba(0,0,0,1)'
      }))

      children.push(new paper.Path.Circle({
        radius: ray,
        strokeColor: 'rgba(0,0,0,1)',
        strokeWidth: 0.2,
        fillColor: 'rgba(0,0,0,0)'
      }))

      children.push(new paper.Path.Circle({
        radius: ray,
        fillColor: 'rgba(255,255,255,0.01)'
      }))


      return new paper.Group({
        children: children,
        name: 'action_icon'
      });
    },
    setPaperEntiteActionHoverSymbol(){
      // let svgIcon = paper.project.importSVG(iconAction);
      // svgIcon.strokeColor = '#01ffe2';
      // svgIcon.strokeWidth = 0.25;
      // svgIcon.scale(0.15);
      // svgIcon.fillColor = null;
      // svgIcon.position = {x:0, y:0};

      // let circle = new paper.Path.Circle({
      //   radius: 3,
      //   fillColor: 'rgba(255,255,255,0.05)'
      // })

      // return new paper.Group({
      //   children: [circle, svgIcon],
      //   name: 'action_icon'
      // });
      let children = [];
      let ray = 0.7; //this.map_item_ray;
      // let pos = {x:0, y:0};
      // let strokewidth = 0.4;

      // children.push(new paper.Path.Line({
      //   from: [- ray, ray],
      //   to: [ray, - ray],
      //   strokeColor: '#01ffe2',
      //   strokeWidth: strokewidth
      // })); 

      // children.push(new paper.Path.Line({
      //   from: [ray, ray],
      //   to: [- ray, - ray],
      //   strokeColor: '#01ffe2',
      //   strokeWidth: strokewidth
      // })); 

      children.push(new paper.Path.Circle({
        radius: ray/2,
        fillColor: '#01ffe2'
      }))

      children.push(new paper.Path.Circle({
        radius: ray,
        strokeColor: '#01ffe2',
        strokeWidth: 0.2,
        fillColor: 'rgba(0,0,0,0)'
      }))

      children.push(new paper.Path.Circle({
        radius: ray,
        fillColor: 'rgba(255,255,255,0.01)'
      }))

      return new paper.Group({
        children: children,
        name: 'action_icon'
      });
    },
    setPaperBesoinSymbol(){
      return new paper.Path({
        pivot: new paper.Point(this.pos),
        segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
        fillColor: '#000'
      })
    },
    setPaperBesoinHoverSymbol(){
      return new paper.Path({
        pivot: new paper.Point(this.pos),
        segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
        fillColor: '#01ffe2'
      })
    },
    setPaperReponseSymbol(){
      return new paper.Path({
        pivot: new paper.Point(this.pos),
        segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
        fillColor: '#eee',
        strokeColor: "#000",
        strokeWidth: 0.25,
      })
    },
    setPaperReponseHoverSymbol(){
      return new paper.Path({
        pivot: new paper.Point(this.pos),
        segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
        fillColor: '#eee',
        strokeColor: "#01ffe2",
        strokeWidth: 0.25,
      })
    },
    async setSuperpositionsMatterConstraints(){
      await nextTick(); // wait for dom to be upadted before applying constraint
      console.log('setSuperpositionsMatterConstraints this.allSuperpositions_clustered', this.allSuperpositions_clustered);
      
      // loop through all supperposition couple
      for(let [cluster_index, cluster] of Object.entries(this.allSuperpositions_clustered)){
        
        for(let [i, cid_eid_A] of cluster.entries()){
          // console.log(`i:${i}, cid_eid_A cid:${cid_eid_A.cid}, eid:${cid_eid_A.eid}`);
          let cid_eid_B = i === cluster.length -1 ? cluster[0] : cluster[i+1];
          // console.log(`i:${i}, cid_eid_B cid:${cid_eid_B.cid}, eid:${cid_eid_B.eid}`);
         
          let concernementA = this.concernementsByID[cid_eid_A.cid];
          // console.log('concernementA', concernementA);
          let concernementB = this.concernementsByID[cid_eid_B.cid];
          // console.log('concernementB', concernementB);

          // console.log('superposition', superposition_id, superposition);
          let mapitemA_id = `${cid_eid_A.cid}___${cluster_index}` 
          let mapitemB_id = `${cid_eid_B.cid}___${cluster_index}` 
          // console.log(`mapitemA_id: ${mapitemA_id}, mapitemB_id: ${mapitemB_id}`);
          
          let mapitemA = this.allMapItems_byid[mapitemA_id];
          let mapitemB = this.allMapItems_byid[mapitemB_id];
          console.log('mapitemA', mapitemA);
          console.log('mapitemB', mapitemB);


          // get the concernement matter bodies with id
          let bodyA = Matter.Composite.get(this.world, mapitemA_id, 'body'); // matter body id is the same as mapitem_id
          let bodyB = Matter.Composite.get(this.world, mapitemB_id, 'body'); // matter body id is the same as mapitem_id
          // console.log('bodyA, bodyB', bodyA, bodyB);
            
          // get the entite coordinates inside the concernement body
          let pointA = null;
          for(let entiteA of concernementA.revisions_byid[concernementA.active_revision].entites){
            if (entiteA.entite && entiteA.entite.id === cid_eid_A.eid && entiteA.display) {
              // console.log('entiteA', entiteA);
              let scale = mapitemA.scale;
              console.log(`mapitemA.scale ${concernementA.id}`, scale);
              pointA = Matter.Vector.create(entiteA.display.pos.x * scale, entiteA.display.pos.y * scale);
              break;
            }
          }
          let pointB = null;
          for(let entiteB of concernementB.revisions_byid[concernementB.active_revision].entites){
            if (entiteB.entite && entiteB.entite.id === cid_eid_B.eid && entiteB.display) {
              // console.log('entiteB', entiteB);
              let scale = mapitemB.scale;
              console.log(`mapitemB.scale ${concernementB.id}`, scale);
              pointB = Matter.Vector.create(entiteB.display.pos.x * scale, entiteB.display.pos.y * scale); 
              break;
            }
          }
          
          // console.log(`pointA:`, pointA,` pointB:`, pointB);
          if (bodyA && bodyB && pointA && pointB) {
            let c = Matter.Constraint.create({
              bodyA: bodyA,
              pointA: pointA,
              bodyB: bodyB,
              pointB: pointB,
              stiffness: 1,
              length: 0,
              damping: 1,
              concernementA: concernementA,
              concernementB: concernementB
            });
            this.superpositions_constraints.push(c);
            Matter.Composite.add(this.world, c);
            // keep a link the constraint into the concernement object (useful for tweening the constraint pointA & pointB in concernementMapItem)
            if(!concernementA.superposition_constraints_id[mapitemA_id]){
              concernementA.superposition_constraints_id[mapitemA_id] = [];
            }
            concernementA.superposition_constraints_id[mapitemA_id].push(c.id);
            if(!concernementB.superposition_constraints_id[mapitemB_id]){
              concernementB.superposition_constraints_id[mapitemB_id] = [];
            }
            concernementB.superposition_constraints_id[mapitemB_id].push(c.id);

            // record all superposed concernements for each concernement
            if (concernementA.all_superposed_concernements_id.indexOf(concernementB.id) < 0) {
              concernementA.all_superposed_concernements_id.push(concernementB.id);
            }
            if (concernementB.all_superposed_concernements_id.indexOf(concernementA.id) < 0) {
              concernementB.all_superposed_concernements_id.push(concernementA.id);
            }
            // record all superposed concernements for each concernement by mapitem_id
            // A
            if (!concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id]) {
              concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id] = []
            }
            if (concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id].indexOf(mapitemB_id) < 0) {
              concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id].push(mapitemB_id);
            }
            // B
            if (!concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id]) {
              concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id] = []
            }
            if (concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id].indexOf(mapitemA_id) < 0) {
              concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id].push(mapitemA_id);
            }

          }
        }
      }
    },
    clearSuperpositionsMatterConstraints(){
      console.log('clearSuperpositionsMatterConstraints', this.superpositions_constraints);
      for(let constraint of this.superpositions_constraints){
        
        // Delete superposition constraints ids recorded in concernement object
        ['A', 'B'].forEach(ab => {
          for( let [mapitem_id, constraint_ids] of Object.entries(constraint[`concernement${ab}`].superposition_constraints_id)){
            let indexes = Object.keys(constraint_ids);
            indexes.forEach(i => {
              if(constraint_ids[i] === constraint.id) {
                delete constraint[`concernement${ab}`].superposition_constraints_id[mapitem_id][i];
              }
            })
          }
        });
        
        Matter.Composite.remove(this.world, constraint, true);
      }
      this.superpositions_constraints = [];
    },
    // resetSuperpositionsMatterConstraints(){
    //   this.clearSuperpositionsMatterConstraints();
    //   this.setSuperpositionsMatterConstraints();
    // },
    onBeforeEngineUpdate(){

    },
    onAfterEngineUpdate(){
      // // START OF DEBUGGING
      // this.debugDrawConstraints()  
      // this.debugDrawWalls()
      // // END OF DEBUGGING
    },
    debugDrawConstraints(){
      // draw lines of constraints for debuging
      let constraints_lines = this.paper.project.getItem({name: 'constraints_lines', class: paper.Group});
      if (constraints_lines) {
        constraints_lines.removeChildren();
      }else{
        constraints_lines = new paper.Group({
          pivot: new paper.Point({x:0,y:0}),
          name: 'constraints_lines',
        });
      }
      let all_constrains = Matter.Composite.allConstraints(this.world);
      let children = [];
      for(let constraint of all_constrains){
        // console.log('constrain', constraint);
        let pointAWorld = Matter.Constraint.pointAWorld(constraint);
        let pointBWorld = Matter.Constraint.pointBWorld(constraint);
        // console.log('pointAWorld, pointBWorld', pointAWorld, pointBWorld);
        children.push(new paper.Path.Line({
          from: [pointAWorld.x, pointAWorld.y],
          to: [pointBWorld.x, pointBWorld.y],
          strokeColor: '#f00',
          strokeWidth: 1
        }));
      }
      constraints_lines.addChildren(children);
    },
    debugDrawWalls(){
      let wall_rects = this.paper.project.getItem({name: 'wall_rects', class: paper.Group});
      if (wall_rects) {
        wall_rects.removeChildren();
      }else{
        wall_rects = new paper.Group({
          pivot: new paper.Point({x:0,y:0}),
          name: 'wall_rects',
        });
      }
      let wallsbody = Matter.Composite.get(this.world, 'walls', 'body');
      if (wallsbody) {
        // console.log('wallsbody', wallsbody.parts);
        let children = [];
        wallsbody.parts.forEach((part, i) => {
          if(i > 0){
            // console.log('part', part.label, part.bounds.min);
            children.push(new paper.Path.Rectangle({
              from: part.bounds.min,
              to: part.bounds.max,
              strokeColor: '#00f',
              strokeWidth: 2
            }));
          }
        });
        wall_rects.addChildren(children);
      }
    },
    closeConcernement(){
      // unfocus any active element to trigger recording if needed
      document.activeElement.blur();
      // setTimeout to let time for editable fields to focus out and record changes
      this.waitForUpdatingEnded();
    },
    waitForUpdatingEnded(){
      setTimeout(() => {
        if (!this.concernement_is_updating_nid) {
          this.resetConcernementOpened();
          this.$router.push({
            name: 'home',
            hash: `#${this.map_mode}`
          });
        } else {
          this.waitForUpdatingEnded();
        }
      }, 1);
      
    }
  },
  beforeUpdate () {
  },
  components: {
    MapGradientBackground,
    ConcernementMapPopup,
    RecitPlayer
  }
}

</script>

<template>
  <div id="map-backgrounds">
    <MapGradientBackground />
  </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 
          title="terrain de vie" href="#terraindevie" @click="setMapMode('terraindevie')"
          :class="{active: map_mode === 'terraindevie'}"
        >
          <span class="icon terraindevie"/> <span class="label"> terrain de vie</span>
        </a>
      </li>
      <li>
        <a 
          title="proximite" href="#proximite" @click="setMapMode('proximite')"
          :class="{ disabled: opened_concernement && !opened_concernement.has_proximites, active: map_mode === 'proximite'}"
        >
          <span class="icon proximite"/> <span class="label"> proximité</span>
        </a>
      </li>
      <li>
        <a 
          title="superposition" href="#superposition" @click="setMapMode('superposition')"
          :class="{ disabled: opened_concernement && !opened_concernement.has_superpositions, active: map_mode === 'superposition'}"
        >
          <span class="icon superposition"/> <span class="label"> superposition</span>
        </a>
      </li>
      <li>
        <a 
          title="puissance d'agir" href="#puissancedagir" @click="setMapMode('puissancedagir')"
          :class="{ 
            disabled: opened_concernement && !opened_concernement.has_puissancedagir && !opened_concernement.can_update,
            active: map_mode === 'puissancedagir'}"
        >
          <span class="icon puissancedagir"/> <span class="label"> puissance d'agir</span>
        </a>
      </li>
      <li>
        <a 
          title="action" href="#action" @click="setMapMode('action')"
          :class="{ disabled: opened_concernement && !opened_concernement.has_agissantes, active: map_mode === 'action'}"
        >
          <span class="icon action"/> <span class="label"> action</span>
        </a>
      </li>
      <li>
        <a 
          title="cercle politique" href="#doleancer" @click="setMapMode('doleancer')"
          :class="{ active: map_mode === 'doleancer'}"
        >
        <!-- disabled: opened_concernement && !opened_concernement.has_doleance,  -->
          <span class="icon doleancer"/> <span class="label"> cercle politique</span>
        </a>
      </li>
    </ul>
  </nav>
  <RecitPlayer />
  <ConcernementMapPopup
    v-if="hover_elmt && hover_elmt.type !== 'doleance_step' && !hover_elmt.no_popup"
    :infos="hover_elmt"
  />

</template>

<style lang="css" scoped>

</style>
