import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
import _createClass from '@babel/runtime/helpers/createClass';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import './index-bbdfb97a.js';
import { Vector3, Vector2, Rendering } from '@crystaldesign/web-planner-logic';
import { getLogger } from '@crystaldesign/diva-core';
import * as THREE from 'three';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass';
import { Vector2 as Vector2$1 } from 'three/src/math/Vector2';
import 'react';
import 'react-dynamic-multi-render';
import 'react/jsx-runtime';
import 'mobx-react-lite';
import '@babel/runtime/helpers/asyncToGenerator';
import '@babel/runtime/helpers/slicedToArray';
import '@babel/runtime/helpers/objectWithoutProperties';
import '@babel/runtime/regenerator';
import '@babel/runtime/helpers/toConsumableArray';
import '@crystaldesign/diva-utils';
import 'mobx';
import 'classnames';
import 'qrcode.react';
import '@babel/runtime/helpers/typeof';
import 'flat';
import 'react-switch';
import 'react-countup';

var PlannerBlender2D3DShader = {
  uniforms: {
    tDiffuse: {
      value: null
    },
    opacity: {
      value: 1.0
    },
    backgroundImg: {
      value: null
    }
  },
  vertexShader: ['varying vec2 vUv;', 'void main() {', '	vUv = uv;', '	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', '}'].join('\n'),
  fragmentShader: ['uniform float opacity;', 'uniform sampler2D tDiffuse;', 'uniform sampler2D backgroundImg;', 'varying vec2 vUv;', 'void main() {', '	vec4 texelForground = texture2D( tDiffuse, vUv );', '   float brightness =  0.34 * texelForground.x + 0.5 *texelForground.y + 0.16 * texelForground.z; ', '	vec4 texelBackground = texture2D( backgroundImg, vUv );', '   if( texelForground.w < 0.001){', '       gl_FragColor = vec4(0, 0, 0, 0.0);', '   }', '   else if( texelBackground.x <  0.3 ){', '       gl_FragColor = vec4(brightness,brightness,brightness, texelForground.w)* 0.8;', '   }', '   else {', '       gl_FragColor = (1.0 - opacity) * vec4(brightness,brightness,brightness,texelForground.w);', '   }', '}'].join('\n')
};

var LOG = getLogger('Planner', 'Planner3DGrid');
var Planner3DGrid = /*#__PURE__*/function () {
  function Planner3DGrid(getPlannerViewConfig, getAllPlannedElements) {
    var _this = this;
    _classCallCheck(this, Planner3DGrid);
    _defineProperty(this, "autoDockingDistance", 40);
    _defineProperty(this, "threeContainer", void 0);
    _defineProperty(this, "doShow3DGrid", false);
    _defineProperty(this, "updatePlannerTrans", void 0);
    _defineProperty(this, "clearSelectionFrom3DGrid", void 0);
    _defineProperty(this, "getAllPlannedElements", void 0);
    _defineProperty(this, "groundPlane", void 0);
    _defineProperty(this, "camera", void 0);
    _defineProperty(this, "renderer", void 0);
    _defineProperty(this, "scene", void 0);
    _defineProperty(this, "sceneTree", void 0);
    //speichert alle Renderings abhängig von Set und ElementId
    _defineProperty(this, "backgroundTex", void 0);
    _defineProperty(this, "backGroundTexChanged", false);
    _defineProperty(this, "canvasWidth", void 0);
    _defineProperty(this, "canvasHeight", void 0);
    _defineProperty(this, "moveIconPerspective", void 0);
    _defineProperty(this, "rotateIconPerspective", void 0);
    _defineProperty(this, "rotationCenter", void 0);
    _defineProperty(this, "isTransforming", false);
    _defineProperty(this, "transformWorldPosLastFrame", void 0);
    _defineProperty(this, "curSelectedElement", void 0);
    //Render Loop
    _defineProperty(this, "blenderPass", null);
    _defineProperty(this, "composer", null);
    /**
     * This function is called when the mouse is up - it clears the selection of the selected object
     * @param event
     */
    _defineProperty(this, "onMouseUpClearSelection", function (event) {
      _this.clearSelectionFrom3DGrid();
      _this.threeContainer.removeEventListener('mouseup', _this.onMouseUpClearSelection);
    });
    /**
     * When this function is called the system computes the intersection with the ground plane
     */
    _defineProperty(this, "getIntersectsGroundPlane", function (sceenPosX, screenPosY) {
      if (!_this.camera) return;
      // x = (x / window.innerWidth) * 2 - 1;
      // y = -(y / window.innerHeight) * 2 + 1;
      var raycaster = new THREE.Raycaster();
      var mouseVector = new THREE.Vector3();
      sceenPosX = sceenPosX / _this.canvasWidth * 2 - 1;
      screenPosY = -(screenPosY / _this.canvasHeight) * 2 + 1;
      //sceenPosX = sceenPosX / this.canvasWidth;
      //screenPosY = screenPosY / this.canvasHeight;
      mouseVector.set(sceenPosX, screenPosY, 0.5);
      raycaster.setFromCamera(new THREE.Vector2(mouseVector.x, mouseVector.y), _this.camera);
      return raycaster.intersectObject(_this.groundPlane, true);
    });
    /**
     * Called when the movement starts
     * @param elementId     elementId of the current selected element
     */
    _defineProperty(this, "startMove", function (setId, elementId) {
      // if (!this.sceneTree.has(setId)) return;
      // if (!this.sceneTree.get(setId)!.has(elementId)) return;
      _this.isTransforming = true;
      // TODO hier das icon ausblenden this.moveIcon2DDiv.style.visibility = "hidden";
      //this.rotateIcon2DDiv.style.visibility = "hidden";

      var allElementsBySet = _this.getAllPlannedElements();
      if (!allElementsBySet.has(setId)) return;
      _this.clearSceneTree(); //Clear the scene if start Move is called previous updateScene
      allElementsBySet.forEach(function (elementsInSet, setId) {
        for (var i = 0; i < elementsInSet.length; i++) {
          _this.updatePlannerElement(elementsInSet[i]);
        }
      });
      LOG.debug('Start transforming', 'Planner3DGrid');
      _this.updatePlannerTrans(setId, elementId, new Vector3(0, 0, 0), 0, 5, 'START', _this.autoDockingDistance);
    });
    /**
     * Called when movement is stopped
     */
    _defineProperty(this, "stopMove", function (setId, elementId) {
      LOG.debug('Stop transforming', 'Planner3DGrid');
      _this.isTransforming = false;
      _this.transformWorldPosLastFrame = undefined;
      if (_this.curSelectedElement != undefined) _this.updatePlannerTrans(setId, elementId, new Vector3(0, 0, 0), 0, 5, 'END', _this.autoDockingDistance);
    });
    /**
     * Called when the rotation starts
     * @param elementId     elementId of the current selected element
     */
    _defineProperty(this, "startRotation", function (setId, elementId) {
      _this.isTransforming = true;
      var allElementsBySet = _this.getAllPlannedElements();
      if (!allElementsBySet.has(setId)) return;
      _this.clearSceneTree();
      allElementsBySet.forEach(function (elementsInSet, setId) {
        for (var i = 0; i < elementsInSet.length; i++) {
          _this.updatePlannerElement(elementsInSet[i]);
        }
      });
      _this.rotationCenter = undefined;
      _this.updatePlannerTrans(setId, elementId, new Vector3(0, 0, 0), 0, 5, 'START', _this.autoDockingDistance);
    });
    /**
     * Called when rotation is stopped
     */
    _defineProperty(this, "stopRotation", function (setId, elementId) {
      _this.isTransforming = false;
      _this.rotationCenter = undefined;
      _this.updatePlannerTrans(setId, elementId, new Vector3(0, 0, 0), 0, 5, 'END', _this.autoDockingDistance);
    });
    /**
     * Handles the translation of the ThreeSVG on the ground
     * @param screenPosX
     * @param screenPosY
     */
    _defineProperty(this, "handleTranslation", function (setId, elementId, screenPos) {
      var intersects = _this.getIntersectsGroundPlane(screenPos.x, screenPos.y);
      if (intersects.length > 0) {
        var _this$sceneTree;
        var curWorldPos = new Vector2(intersects[0].point.x, intersects[0].point.z);
        LOG.debug('MOVE TO WORLD POS ' + curWorldPos.toString(), 'Planner3DGrid');

        //First frame for detecting collision
        if (!_this.transformWorldPosLastFrame) {
          _this.transformWorldPosLastFrame = curWorldPos;
          return;
        }
        var moveDir = new Vector2(curWorldPos.x - _this.transformWorldPosLastFrame.x, curWorldPos.y - _this.transformWorldPosLastFrame.y);
        var sceneElement = (_this$sceneTree = _this.sceneTree) === null || _this$sceneTree === void 0 ? void 0 : _this$sceneTree.get(setId).get(elementId);
        if (!sceneElement) return;
        sceneElement.position.x += moveDir.x;
        sceneElement.position.z += moveDir.y;
        if (_this.curSelectedElement != undefined) _this.updatePlannerTrans(_this.curSelectedElement.getSetId(), _this.curSelectedElement.getElementId(), new Vector3(moveDir.x * 100, 0, moveDir.y * 100), 0, 5, 'UPDATE', _this.autoDockingDistance);
        _this.transformWorldPosLastFrame = curWorldPos;
      }
    });
    /**
     * Handles the rotation of the ThreeSVG on the ground
     * @param screenPosX
     * @param screenPosY
     */
    _defineProperty(this, "handleRotation", function (setId, elementId, screenPos) {
      var intersects = _this.getIntersectsGroundPlane(screenPos.x, screenPos.y);
      if (intersects.length > 0) {
        var _this$sceneTree2;
        var sceneElement = (_this$sceneTree2 = _this.sceneTree) === null || _this$sceneTree2 === void 0 ? void 0 : _this$sceneTree2.get(setId).get(elementId);
        if (!sceneElement) return;
        var curWorldPos = new Vector2(intersects[0].point.x, intersects[0].point.z);
        if (_this.rotationCenter) {
          var rotDir = new Vector2(curWorldPos.x - sceneElement.position.x, curWorldPos.y - sceneElement.position.z);
          var refDir = new Vector2(0, 1);
          var angleRad = Vector2.angleRad(rotDir, refDir);
          if (curWorldPos.x < sceneElement.position.x) angleRad = 2 * Math.PI - angleRad;
          var deltaRotRad = sceneElement.rotation.z - angleRad;
          sceneElement.rotation.z = angleRad;
          if (_this.curSelectedElement != undefined) _this.updatePlannerTrans(_this.curSelectedElement.getSetId(), _this.curSelectedElement.getElementId(), new Vector3(0, 0, 0), deltaRotRad * 180 / Math.PI, 5, 'UPDATE', _this.autoDockingDistance);
        } else {
          _this.rotationCenter = curWorldPos;
        }
      }
    });
    /**
     * Render loop
     */
    _defineProperty(this, "run", function () {
      if (!_this.doShow3DGrid || _this.renderer == null) return;
      if (_this.backgroundTex == null) return;
      var that = _this;
      var timeout = _this.isTransforming ? 30 : 10;
      setTimeout(function () {
        var _requestAnimationFram;
        (_requestAnimationFram = requestAnimationFrame) === null || _requestAnimationFram === void 0 || _requestAnimationFram(that.run);
      }, 1000 / timeout);
      if (_this.backGroundTexChanged) {
        _this.backGroundTexChanged = false;
        _this.blenderPass.uniforms['backgroundImg'].value = _this.backgroundTex;
      }
      _this.composer.render();
    });
    this.getAllPlannedElements = getAllPlannedElements;
    this.sceneTree = new Map();
    this.curSelectedElement = undefined;
    this.threeContainer = null;
  }
  return _createClass(Planner3DGrid, [{
    key: "setCallbackMethods",
    value: function setCallbackMethods(updatePlannerTrans) {
      this.updatePlannerTrans = updatePlannerTrans;
    }

    /**
     * Initialize the 3D Grid
     * @param imageContainer    The imageContainer where the canvas is rendered into
     * @param canvasWidth       The width of the canvas
     * @param canvasHeight      The height of the canvas
     */
  }, {
    key: "initialize",
    value: function initialize(canvasWidth, canvasHeight) {
      LOG.debug('Initialize Planner3D Grid! ', 'ViewPlanner3DGrid - initialize');
      this.canvasWidth = canvasWidth;
      this.canvasHeight = canvasHeight;
      this.threeContainer = document.getElementById('diva3dImg_3DGrid');
      if (!this.threeContainer) return;
      this.scene = new THREE.Scene();
      this.camera = new THREE.PerspectiveCamera(24, canvasWidth / canvasHeight, 0.1, 1000);
      this.renderer = new THREE.WebGLRenderer({
        alpha: true,
        antialias: true
      });
      this.renderer.setClearColor(0x000000, 0);
      this.renderer.setSize(canvasWidth, canvasHeight);

      //Init ground plane
      var groundPlaneGeo = new THREE.PlaneGeometry(100, 100);
      var groundMat = new THREE.MeshLambertMaterial({
        color: 0x0000ff,
        transparent: true,
        opacity: 0
      });
      this.groundPlane = new THREE.Mesh(groundPlaneGeo, groundMat);
      this.groundPlane.rotation.x = -Math.PI / 2;
      this.scene.add(this.groundPlane);
      this.camera.position.z = -3;

      //Init background.

      this.backgroundTex = new THREE.Texture();
      this.threeContainer.appendChild(this.renderer.domElement);
      this.doShow3DGrid = false;
      this.composer = new EffectComposer(this.renderer);
      this.composer.addPass(new RenderPass(this.scene, this.camera));
      this.blenderPass = new ShaderPass(PlannerBlender2D3DShader);
      this.blenderPass.uniforms['opacity'].value = 0.92;
      this.blenderPass.renderToScreen = true;
      this.composer.addPass(this.blenderPass);
    }

    /**
     * Destroy the whole Planner3D Grid and all three.js components
     */
  }, {
    key: "destroy",
    value: function destroy(plannerUIHandler) {
      var _this$threeContainer;
      if (!this.threeContainer) return;
      LOG.debug('Destroy Planner3D Grid! ', 'ViewPlanner3DGrid - destroy');
      this.hide3DGrid();
      plannerUIHandler.clear3DGridUI();
      this.clearSceneTree();
      this.hide3DGrid();
      this.scene = undefined;
      this.sceneTree.clear();
      //this.threeContainer.parentNode.removeChild(this.threeContainer);
      // if (this.threeContainer && this.threeContainer!.hasChildNodes)
      if ((_this$threeContainer = this.threeContainer) !== null && _this$threeContainer !== void 0 && _this$threeContainer.firstChild) this.threeContainer.removeChild(this.threeContainer.firstChild);
      this.backgroundTex = null;
      this.composer = null;
      this.blenderPass = null;
      this.camera = undefined;
      this.moveIconPerspective = null;
      this.rotateIconPerspective = null;
      this.groundPlane = null;
      this.renderer = undefined;
    }
  }, {
    key: "rotToThreeRot",
    value:
    /**
     * Converts the  rotation from rendering information into the associated three rotation
     * @param unityQuat
     */
    function rotToThreeRot(rot) {
      var quat = new THREE.Quaternion();
      quat.setFromEuler(new THREE.Euler(rot.x * Math.PI / 180, rot.y * Math.PI / 180, rot.z * Math.PI / 180));
      quat.w *= -1;
      var v = new THREE.Euler();
      v.setFromQuaternion(quat);
      v.y += Math.PI; //Y is 180 degreee off
      v.z *= -1; //flip z
      return v;
    }

    /**
     * Converts the unity position into the three position
     * @param unityPos
     */
  }, {
    key: "posToThreePos",
    value: function posToThreePos(pos) {
      return new Vector3(pos.x / 100.0, pos.y / 100.0, pos.z / 100.0);
    }

    /**
     * This function clears all objects in the three.js scene.
     */
  }, {
    key: "clearSceneTree",
    value: function clearSceneTree() {
      var _this2 = this;
      this.sceneTree.forEach(function (elementsInTree, setId) {
        elementsInTree.forEach(function (sceneModel, elementId) {
          _this2.scene.remove(sceneModel);
        });
      });
    }

    /**
     * This function sets the camera transformation in the three.js scene the same like the camera in unity.
     * @param rendering     The rendering coming from Unity - it holds all informations to the camera transformation
     */
  }, {
    key: "updateCamera",
    value: function updateCamera(rendering) {
      if (!this.camera) return;
      var unityCamInfo = rendering.getCamInfo();
      if (!unityCamInfo) return;
      var camPos = this.posToThreePos(unityCamInfo.pos);
      this.camera.rotation.copy(this.rotToThreeRot(unityCamInfo.rot));
      this.camera.position.x = camPos.x;
      this.camera.position.y = camPos.y;
      this.camera.position.z = camPos.z;
      this.camera.updateMatrixWorld();
    }

    /**
     * This function updates the interaction icons movement and rotation
     * @param plannerElement    The planner element where the rotation and movement icon should be placed
     */
  }, {
    key: "updateInteractionIcons",
    value: function updateInteractionIcons(plannerUIHandler, plannerElement) {
      var offsetVecMove2D = new Vector2(-0.15, plannerElement.getHeightOLT() / 100.0 / 2.0 + 0.15);
      offsetVecMove2D = Vector2.rotateOrigin(offsetVecMove2D, plannerElement.getRotDeg());
      var moveIconWorldPos = new THREE.Vector3(plannerElement.getWorldPosCenter().x / 100 + offsetVecMove2D.x, 0, plannerElement.getWorldPosCenter().z / 100 + offsetVecMove2D.y);
      var screenPosMove = Vector2.convertToVector2(this.convertWorldPosToScreenPos(moveIconWorldPos));
      if (screenPosMove == undefined) return;
      var offsetVecRot2D = new Vector2(0.15, plannerElement.getHeightOLT() / 100.0 / 2.0 + 0.15);
      offsetVecRot2D = Vector2.rotateOrigin(offsetVecRot2D, plannerElement.getRotDeg());
      var rotIconWorldPos = new THREE.Vector3(plannerElement.getWorldPosCenter().x / 100 + offsetVecRot2D.x, 0, plannerElement.getWorldPosCenter().z / 100 + offsetVecRot2D.y);
      var screenPosRot = Vector2.convertToVector2(this.convertWorldPosToScreenPos(rotIconWorldPos));
      if (screenPosRot == undefined) return;
      //Calculate correct position so that they do not overlap
      var centerPointBetweenIcons = new Vector2((screenPosMove.x + (screenPosRot === null || screenPosRot === void 0 ? void 0 : screenPosRot.x)) / 2, (screenPosMove.y + screenPosRot.y) / 2);
      var dirCenterMove = Vector2.getDirection(screenPosMove, centerPointBetweenIcons);
      var dirCenterRot = Vector2.getDirection(screenPosRot, centerPointBetweenIcons);
      var finalPosMove = Vector2.add(Vector2.mulNum(Vector2.normalize(dirCenterMove), 25 + 7), centerPointBetweenIcons);
      finalPosMove.interpretation = 'pixel';
      var finalPosRot = Vector2.add(Vector2.mulNum(Vector2.normalize(dirCenterRot), 25 + 7), centerPointBetweenIcons);
      finalPosRot.interpretation = 'pixel';
      plannerUIHandler.addMove3DGrid(plannerElement.getSetId(), plannerElement.getElementId(), finalPosMove, this.startMove, this.handleTranslation, this.stopMove);
      plannerUIHandler.addRot3DGrid(plannerElement.getSetId(), plannerElement.getElementId(), finalPosRot, this.startRotation, this.handleRotation, this.stopRotation);
    }

    /**
     * Updates the planner Element and draws the svg icon on the ground. The selected element gets also rotation and translation icons
     * @param plannerElement
     * @param isSelectedElem
     */
  }, {
    key: "updatePlannerElement",
    value: function updatePlannerElement(plannerElement) {
      if (!plannerElement.hasSvgDataOLTBase64() || !this.renderer || !this.scene) return;

      //var texture = new THREE.Texture(plannerElement.getSvgDataOLTBase64 ());
      var texture = new THREE.TextureLoader().load(plannerElement.getSvgDataOLTBase64());
      texture.wrapS = THREE.RepeatWrapping;
      texture.wrapT = THREE.RepeatWrapping;
      texture.generateMipmaps = true;
      texture.anisotropy = this.renderer.capabilities.getMaxAnisotropy();
      //texture.needsUpdate = true;
      var geoWidth = plannerElement.getWidthOLT() / 100;
      var geoHeight = plannerElement.getHeightOLT() / 100;
      var geometry = new THREE.PlaneGeometry(geoWidth, geoHeight);
      var material = new THREE.MeshBasicMaterial({
        map: texture
      });
      var plannerElementMesh = new THREE.Mesh(geometry, material);
      plannerElementMesh.rotation.z = -plannerElement.getRotRad();
      plannerElementMesh.rotation.x = -Math.PI / 2;
      plannerElementMesh.position.x = plannerElement.getWorldPosCenter().x / 100;
      plannerElementMesh.position.y = plannerElement.getLayer() / 500;
      plannerElementMesh.position.z = plannerElement.getWorldPosCenter().z / 100;
      if (!this.sceneTree.has(plannerElement.getSetId())) this.sceneTree.set(plannerElement.getSetId(), new Map());
      this.sceneTree.get(plannerElement.getSetId()).set(plannerElement.getElementId(), plannerElementMesh);
      this.scene.add(plannerElementMesh);
    }

    /**
     * This scene is called when a new Rendering is made. The whole scene Tree is updated and the SVGs are placed in the Tree.JS world
     * @param plannerElements
     */
  }, {
    key: "updateScene",
    value: function updateScene(plannerUIHandler, rendering, curSelectedElement, plannerElementsDict, renderSize) {
      var _this3 = this;
      if (!this.renderer && !this.camera) return;
      plannerUIHandler.clear3DGridUI();
      this.show3DGrid();
      this.clearSceneTree();
      this.curSelectedElement = curSelectedElement;
      this.initBackgroundScene(rendering);
      this.canvasWidth = renderSize.imgWidth;
      this.canvasHeight = renderSize.imgHeight;
      var camInfo = rendering.getCamInfo();
      if (this.renderer && this.renderer.getSize(new THREE.Vector2()).x != renderSize.imgWidth || this.renderer.getSize(new THREE.Vector2()).y != renderSize.imgHeight || (camInfo === null || camInfo === void 0 ? void 0 : camInfo.vertFov) != this.camera.fov) {
        this.camera.fov = camInfo.vertFov;
        this.camera.aspect = renderSize.imgWidth / renderSize.imgHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(renderSize.imgWidth, renderSize.imgHeight);
      }

      // this.debugScene();
      this.updateCamera(rendering);
      plannerElementsDict.forEach(function (allPlannedElements, setId) {
        for (var i = 0; i < allPlannedElements.length; i++) {
          if (curSelectedElement != undefined && allPlannedElements[i].getElementId() == curSelectedElement.getElementId()) _this3.updateInteractionIcons(plannerUIHandler, allPlannedElements[i]);
        }
      });
    }

    /**
     * Sets up the background scene (layermask of the rendering)
     * @param rendering
     */
  }, {
    key: "initBackgroundScene",
    value: function initBackgroundScene(rendering) {
      if (!rendering.HasLayerMaskThreeTexture) {
        var textureLoader = new THREE.TextureLoader();
        rendering.LayerMaskThreeTexture = textureLoader.load(rendering.getLayerMaskForSrc());
      }
      this.backgroundTex = rendering.LayerMaskThreeTexture;
      this.backGroundTexChanged = true;
    }
  }, {
    key: "isInTrasnformMode",
    value:
    /**
     * This function returns true if the 3D Grid is currently in the transformation mode (translating or rotating)
     */
    function isInTrasnformMode() {
      return this.isTransforming;
    }

    /**
     * This function is called when the 3D Grid should be shown. (User starts interaction with scene)
     */
  }, {
    key: "show3DGrid",
    value: function show3DGrid() {
      if (!this.doShow3DGrid) {
        this.doShow3DGrid = true;
        this.run();
      }
    }

    /**
     * This function is called when the 3D Grid should be hidden. (The user releases interaction - only 3D image is shown.)
     */
  }, {
    key: "hide3DGrid",
    value: function hide3DGrid() {
      if (!this.renderer) return;
      if (this.doShow3DGrid) {
        this.renderer.clear();
        this.doShow3DGrid = false;
      }
    }

    /**
     * This function is called to update the user Interface elements of the 3D Grid
     * @param curSelectedPlannerElement
     */
  }, {
    key: "updateUI",
    value: function updateUI(plannerUIHandler, curSelectedPlannerElement) {
      plannerUIHandler.clear3DGridUI();
      this.curSelectedElement = curSelectedPlannerElement;
      this.show3DGrid();
      this.updateInteractionIcons(plannerUIHandler, curSelectedPlannerElement);
    }
  }, {
    key: "getPositionOfCanvasContainer",
    value: function getPositionOfCanvasContainer() {
      return new Vector2(0, 0);
    }
  }, {
    key: "convertWorldPosToScreenPos",
    value: function convertWorldPosToScreenPos(worldPos) {
      var pos = worldPos.clone();
      pos.project(this.camera);
      var widthHalf = this.canvasWidth / 2;
      var heightHalf = this.canvasHeight / 2;
      pos.x = pos.x * widthHalf + widthHalf;
      pos.y = -(pos.y * heightHalf) + heightHalf;
      return new Vector2$1(pos.x, pos.y);
    }
  }]);
}();

var Planner3DImageUI = /*#__PURE__*/function () {
  function Planner3DImageUI(getConfiguratorState, plannerPaletteViewInfo, settingsState) {
    _classCallCheck(this, Planner3DImageUI);
    this.settingsState = settingsState;
    _defineProperty(this, "uiHTMLContainer", void 0);
    _defineProperty(this, "classUI", 'wc3DImageUI');
    _defineProperty(this, "getConfiguratorState", void 0);
    _defineProperty(this, "plannerPaletteViewInfo", void 0);
    this.getConfiguratorState = getConfiguratorState;
    this.plannerPaletteViewInfo = plannerPaletteViewInfo;
  }

  /**
   * This function adds the trash icon (deletion) on the 3D image.
   * The position is computed based on the informations from the rendering
   * @param element   The elements where the icon should be displayed
   * @param posXPercent   The procentual X position of the deletion icon when it should be displayd on TOP_RIGHT_BACK config
   * @param posYPercent   The procentual Y position of the deletion icon when it should be displayd on TOP_RIGHT_BACK config
   */
  return _createClass(Planner3DImageUI, [{
    key: "addDelIcon",
    value: function addDelIcon(plannerUIHandler, element, posXPercent, posYPercent) {
      if (posXPercent > 100 || posXPercent < 0 || posYPercent > 100 || posYPercent < 0) return;
      plannerUIHandler.addTrashIconUI(element.getSetId(), element.getElementId(), element.getRotDeg(), new Vector2(posXPercent, posYPercent, 'percentage'), element.getPlannerType() == 'BOX' ? 'BOX' : '3D');
    }
  }, {
    key: "addDimensionInfo",
    value: function addDimensionInfo(plannerUIHandler, setId, element, rendering) {
      var alternateRenderInfo = rendering.getAlternateRenderInfo();
      if (rendering.getAlternateRenderingsExist() && alternateRenderInfo == undefined) return; //Only display the dimensions when no door is shown
      var elementId = element.parentElementId + '.' + element.shelfGridId + '.' + element.shelfRasterHeight;
      var position = rendering.getLeftBottomFrontUIPos(setId, elementId);
      if (!position) return;
      if (position.x < 0 || position.x > 100) return;
      if (position.y < 0 || position.y > 100) return;
      var distVal = Math.round(rendering.getDistanceToGround(setId, elementId));
      if (distVal == -1) return;
      plannerUIHandler.addDistanceFromGround(setId, element.parentElementId, distVal, position);
    }

    /**
     * This function adds the position number to the 3D image. It returns the position of the number on the screen and its width
     * @param element
     * @param posXPercent
     * @param posYPercent
     * @param elemIsSelected
     * @param elemIsSelectable
     */
  }, {
    key: "addPosNrUI",
    value: function addPosNrUI(plannerUIHandler, element, posXPercent, posYPercent, elemIsSelected, elemIsSelectable) {
      var _plannerUIHandler$get;
      if (posXPercent < 0) posXPercent = 0;
      if (posXPercent > 100) posXPercent = 100;
      if (posYPercent < 0) posYPercent = 0;
      if (posYPercent > 100) posYPercent = 100;
      plannerUIHandler.addPosNrUI(element.getSetId(), element.getElementId(), element.getIsDockedAccessoire(), new Vector2(posXPercent, posYPercent, 'percentage'), element.getRotDeg(), 1, (_plannerUIHandler$get = plannerUIHandler.getPosNrByBasketId(element.getBasketId())) === null || _plannerUIHandler$get === void 0 ? void 0 : _plannerUIHandler$get.toString(), elemIsSelected ? 'selected' : elemIsSelectable ? 'selectable' : 'unselectable', '3D');
    }

    /**
       * This function adds the docking points of the box planner. It is the docking point for docking to left and right and if the element is the top element in the colum
       * it also adds the add to top. 
       * @param element   The current selected element
       * @param rendering The rendering that holds the information about the screen positions
        */
  }, {
    key: "addBoxPlannerDockingPoints",
    value: function addBoxPlannerDockingPoints(plannerUIHandler, element, rendering) {
      var displayTopDP = false;
      var avoDP = element.getFreeDockingPointByTypeAndNumber('AVO', 1);
      if (avoDP != undefined && !avoDP.IsDisabled) displayTopDP = true; //The dockingpoint can be disabled when e.g. the max count of elements per col is reached

      var leftCenter = rendering.getBoxPlannerCornerUIPos(element.getSetId(), element.getElementId(), 'LEFTCENTER');
      if (leftCenter) plannerUIHandler.addCopy(element.getSetId(), element.getElementId(), 'BoxCopyLeft', leftCenter, '3D');
      var rightCenter = rendering.getBoxPlannerCornerUIPos(element.getSetId(), element.getElementId(), 'RIGHTCENTER');
      if (rightCenter) plannerUIHandler.addCopy(element.getSetId(), element.getElementId(), 'BoxCopyRight', rightCenter, '3D');
      if (displayTopDP) {
        var topCenter = rendering.getBoxPlannerCornerUIPos(element.getSetId(), element.getElementId(), 'TOPCENTER');
        if (topCenter) plannerUIHandler.addCopy(element.getSetId(), element.getElementId(), 'BoxCopyTop', topCenter, '3D');
      }
    }
  }, {
    key: "addCopyIcon",
    value: function addCopyIcon(plannerUIHandler, element) {
      plannerUIHandler.addCopy(element.getSetId(), element.getElementId(), 'CopyElement', new Vector2(0, 0), '3D');
    }

    /**
     * This function adds the accessoire DockingPoints on the 3D Image.
     * @param element   The current element
     * @param viewDockingPointList
     * @param selectedDP
     */
  }, {
    key: "addAccDockingPoints",
    value: function addAccDockingPoints(plannerUIHandler, element, viewDockingPointList, typeOnly) {
      var allDockingPoints = element.getAllDockingPoints();
      for (var i = 0; i < allDockingPoints.length; i++) {
        var _this$plannerPaletteV;
        var dp = allDockingPoints[i];
        if ((_this$plannerPaletteV = this.plannerPaletteViewInfo) !== null && _this$plannerPaletteV !== void 0 && (_this$plannerPaletteV = _this$plannerPaletteV.plannerConfiguration.hideAVButtons) !== null && _this$plannerPaletteV !== void 0 && _this$plannerPaletteV.includes(dp.Type)) continue;
        if ((dp.Type == 'AVO' || dp.Type == 'AVC' || dp.Type == 'AVU' || dp.Type == 'AVS' || dp.Type == 'AVN') && typeOnly == undefined || typeOnly === dp.Type) {
          for (var j = 0; j < viewDockingPointList.length; j++) {
            if (dp.Name == viewDockingPointList[j].N) {
              //Man kann ihn anzeigen.

              plannerUIHandler.addDP(element.getSetId(), element.getElementId(), dp.DpId, 'ACC', dp.IsDocking ? 'DOCKING' : 'NOT_DOCKING', dp.OnElementId, element.getRotDeg(), 0, new Vector2(viewDockingPointList[j].x, viewDockingPointList[j].y, 'percentage'), '3D');
            }
          }
        }
      }
    }
  }, {
    key: "addOutlinePolygon",
    value: function addOutlinePolygon(plannerUIHandler, rendering, plannerElement, state, viewPortSize) {
      var outlineInfo = rendering.getOutlinePolygonForSVG(plannerElement.getSetId(), plannerElement.getElementId(), viewPortSize);
      if (outlineInfo) {
        plannerUIHandler.addOutline3D(plannerElement.getSetId(), plannerElement.getElementId(), outlineInfo.points, outlineInfo.avgCamDist, state, plannerElement.getPlannerType() == 'BOX');
      }
    }

    /**
     * Initializes the UI of the 3D image
     * @param htmlContainer     The html Container where the UI should be rendered into
     */
  }, {
    key: "initialize",
    value: function initialize(htmlContainer) {
      if (!this.uiHTMLContainer) {
        this.uiHTMLContainer = document.createElement('div');
        this.uiHTMLContainer.classList.add(this.classUI);
        htmlContainer.appendChild(this.uiHTMLContainer);
      }
    }

    /**
     * Update the UserInterface on the 3D image.
     * @param allPlannedElements    A list
     * @param rendering
     * @param selectedElements
     * @param selectableElements
     * @param setAllElementsSelectable
     * @param selectedDP
     */
  }, {
    key: "updateUI",
    value: function updateUI(plannerUIHandler, allPlannedElementsDict, allVisualizedNotPlannedElementsDict, rendering, selectedElementsDict, selectableElementsDict, setAllElementsSelectable, selectedDP, viewPortSize) {
      var _this = this;
      //Run through all position Elements and look if they are visible in the UIInfo

      plannerUIHandler.clear2D3DViewerUI();
      allPlannedElementsDict.forEach(function (allPlannedElements, setId) {
        for (var i = 0; i < allPlannedElements.length; i++) {
          var element = allPlannedElements[i];
          if (!rendering.hasUIInfosOfElement(element.getSetId(), element.getElementId())) continue;
          var elemIsSelected = false;
          var elemIsSelectable = setAllElementsSelectable;
          //TODO only show number of acccessoire if one of the accessoires or parent is selected
          if (selectedElementsDict.has(setId)) {
            var selectedElements = selectedElementsDict.get(setId);
            var selectedElemetIds = selectedElements.map(function (item) {
              return item.getElementId();
            });
            elemIsSelected = selectedElemetIds.includes(element.getElementId());
          }
          if (!elemIsSelected && !setAllElementsSelectable) {
            if (selectableElementsDict.has(setId)) {
              var selectableElements = selectableElementsDict.get(setId);
              for (var j = 0; j < selectableElements.length; j++) {
                if (element.getElementId() == selectableElements[j].getElementId()) {
                  elemIsSelectable = true;
                  break;
                }
              }
            }
          }
          _this.addOutlinePolygon(plannerUIHandler, rendering, element, elemIsSelected ? 'selected' : elemIsSelectable ? 'selectable' : 'unselectable', viewPortSize);
          switch (element.getPlannerType()) {
            case 'STD':
              {
                var isPlanner = ['PLANNER', 'PRODUCTS', 'PROMOTED', 'PLANNER_2.0'].includes(_this.getConfiguratorState());
                var _elemUIInfo = rendering.getLeftTopBackUIPos(element.getSetId(), element.getElementId());
                if (_elemUIInfo && (!_this.settingsState.posNrAreHidden || isPlanner)) _this.addPosNrUI(plannerUIHandler, element, _elemUIInfo.x, _elemUIInfo.y, elemIsSelected, elemIsSelectable);
                if (elemIsSelected) {
                  if (isPlanner) {
                    if (element.getIsDockedAccessoire()) {
                      _this.addAccDockingPoints(plannerUIHandler, element, rendering.getAllDockingPoints(element.getSetId(), element.getElementId()), 'AVO');
                    } else {
                      _this.addAccDockingPoints(plannerUIHandler, element, rendering.getAllDockingPoints(element.getSetId(), element.getElementId()));
                    }
                    var _elemUIInfo2 = rendering.getRightTopBackUIPos(element.getSetId(), element.getElementId());
                    _this.addDelIcon(plannerUIHandler, element, _elemUIInfo2.x, _elemUIInfo2.y);
                    _this.addCopyIcon(plannerUIHandler, element);
                  }
                }
                //if this is the ACC_PLANNER step the accessoreis show the deleteIcon
                if (_this.getConfiguratorState() == 'ACC_PLANNER' && element.getIsDockedAccessoire()) {
                  var _elemUIInfo3 = rendering.getRightTopBackUIPos(element.getSetId(), element.getElementId());
                  _this.addDelIcon(plannerUIHandler, element, _elemUIInfo3.x, _elemUIInfo3.y);
                }
              }
              break;
            case 'BOX':
              var elemUIInfo = rendering.getBoxPlannerCornerUIPos(element.getSetId(), element.getElementId(), 'RIGHTTOPFRONT');
              if (elemUIInfo) {
                _this.addPosNrUI(plannerUIHandler, element, elemUIInfo.x, elemUIInfo.y, elemIsSelected, elemIsSelectable);
              }
              if (elemIsSelected) {
                _this.addBoxPlannerDockingPoints(plannerUIHandler, element, rendering);
                if (!_this.checkBoxPlannerSingleElement(allPlannedElements) && element.getFreeDockingPointByTypeAndNumber('AVO', 1) != undefined) {
                  //Only display Delete Icon for boxPlanner when there is more than 1 element and the element has no element on top
                  var posBoxTrash = rendering.getBoxPlannerCornerUIPos(element.getSetId(), element.getElementId(), 'RIGHTTOPFRONT');
                  if (posBoxTrash) _this.addDelIcon(plannerUIHandler, element, posBoxTrash.x, posBoxTrash.y);
                }
              }
              break;
          }
        }
      });
      allVisualizedNotPlannedElementsDict.forEach(function (allVisualizedNotPlannedElements, setId) {
        for (var i = 0; i < allVisualizedNotPlannedElements.length; i++) {
          var element = allVisualizedNotPlannedElements[i];
          if (element.isShelfAcc) _this.addDimensionInfo(plannerUIHandler, setId, element, rendering);
        }
      });
    }

    /**
     * This function returns true if only one Element is left.
     * If the backside module is activated, it is also one element left, if the two are opposite
     */
  }, {
    key: "checkBoxPlannerSingleElement",
    value: function checkBoxPlannerSingleElement(allPlannerElements) {
      if (allPlannerElements.length == 1) return true;
      if (allPlannerElements.length == 2) {
        var dockingPoints1 = allPlannerElements[0].getAllDockingPoints();
        var dockingPoints2 = allPlannerElements[0].getAllDockingPoints();
        for (var i = 0; i < dockingPoints1.length; i++) {
          var dockingPoint1 = dockingPoints1[i];
          for (var j = 0; j < dockingPoints2.length; j++) {
            var dockingPoint2 = dockingPoints2[j];
            if (dockingPoint1.IsDocking && dockingPoint2.IsDocking && dockingPoint1.Number == 2 && dockingPoint2.Number == 2 && (dockingPoint1.Type == 'AVO' || dockingPoint1.Type == 'AVU')) return true;
          }
        }
      }
      return false;
    }

    /**-------------------------Getter ------------------------------- */
  }, {
    key: "Class3DUI",
    get: function get() {
      return this.classUI;
    }
  }]);
}();

var Planner3DImage = /*#__PURE__*/function () {
  function Planner3DImage(getConfiguratorState, update3DImgSrcInView, getPlannerViewConfig, onDoShowNav3DChanged, getAllPlannedElements, plannerPaletteViewInfo, settingsState) {
    _classCallCheck(this, Planner3DImage);
    _defineProperty(this, "imageContainer", undefined);
    _defineProperty(this, "UIHandler", void 0);
    _defineProperty(this, "curRendering", void 0);
    _defineProperty(this, "planner3DGrid", void 0);
    _defineProperty(this, "update3DImgSrcInView", void 0);
    _defineProperty(this, "onDoShowNav3DChanged", void 0);
    //Navigation
    _defineProperty(this, "enablePlanner3DGrid", void 0);
    this.UIHandler = new Planner3DImageUI(getConfiguratorState, plannerPaletteViewInfo, settingsState);
    this.curRendering = new Rendering('Placeholder', 'Placeholder', '', -1, -1, false, false, 0, false, false, 'STREAM');
    this.planner3DGrid = new Planner3DGrid(getPlannerViewConfig, getAllPlannedElements);
    this.onDoShowNav3DChanged = onDoShowNav3DChanged;
    //this.getConfiguratorState = getConfiguratorState;
    this.enablePlanner3DGrid = false;
    this.update3DImgSrcInView = update3DImgSrcInView;
  }
  /*
    private onDragStart = (e: any) => {
        e.preventDefault();
    };
    */
  /**
   * This function is called to initialize the view of the 3D Image. All HTML components are created and the three.js canvas is initialized.
   * @param htmlElementID The Html Id where the image should be rendered
   * @param canvasSize   The size of the container - used for Threejs canvas initialization
   */
  return _createClass(Planner3DImage, [{
    key: "initialize",
    value: function initialize(htmlElementID, updatePlannerTrans) {
      this.imageContainer = document.getElementById(htmlElementID);
      this.planner3DGrid.setCallbackMethods(updatePlannerTrans);
      if (this.imageContainer) {
        this.UIHandler.initialize(this.imageContainer);
      }
    }

    /**
     * This function is called when the visualization state of the 3D Grid changed. The 3D Grid is shown or hidden.
     * @param canvasSize        The size the 3D canvas is rendered into
     * @param forceClose        if true - the 3D grid is closed and ignores the state
     */
  }, {
    key: "handlePlanner3DGridChanged",
    value: function handlePlanner3DGridChanged(plannerUIHandler, canvasSize, forceClose, forceActivate) {
      if (forceClose) {
        if (this.enablePlanner3DGrid) {
          this.enablePlanner3DGrid = false;
          this.planner3DGrid.destroy(plannerUIHandler);
        }
      } else {
        var prevWasActive = this.enablePlanner3DGrid;
        if (forceActivate) this.enablePlanner3DGrid = true;else this.enablePlanner3DGrid = !this.enablePlanner3DGrid;
        if (prevWasActive && !this.enablePlanner3DGrid) {
          this.planner3DGrid.destroy(plannerUIHandler);
        } else if (!prevWasActive && this.enablePlanner3DGrid) {
          this.planner3DGrid.initialize(canvasSize.imgWidth, canvasSize.imgHeight);
        }
      }
    }

    /**
     * Clear all views - 2D Grid/ 3D Grid and 3D image
     */
  }, {
    key: "clearView",
    value: function clearView(plannerUIHandler) {
      this.planner3DGrid.destroy(plannerUIHandler);
      this.curRendering = new Rendering('Placeholder', 'Placeholder', '', -1, -1, false, false, 0, false, false, 'STREAM');
      this.update3DImgSrcInView('data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='); //"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" basis a blank white image
    }

    /**
     * returns true if the Planner3D Grid is enabled
     *
     */
  }, {
    key: "getPlanner3DGridEnabled",
    value: function getPlanner3DGridEnabled() {
      return this.enablePlanner3DGrid;
    }
  }, {
    key: "getPlanner3DGridIsInTransformMode",
    value: function getPlanner3DGridIsInTransformMode() {
      return this.planner3DGrid.isInTrasnformMode();
    }

    /**
     * This function is called when the user Interface of the current rendering has to be updated. This can be the case when the planner Changed or the configurator step changed.
     * @param selectedElements
     * @param selectableElements
     * @param setAllElementsSelectable if this is set the elements in the selectableElements are ignored and all Elements that are not selected are declared to be selectable
     */
  }, {
    key: "updateUI",
    value: function updateUI(plannerUIHandler, allPlannedElements, allVisualizedNotPlannedElements, selectedElementsDict, selectableElements, setAllElementsSelectable, selectedDP, viewPortSize) {
      var _this = this;
      if (this.enablePlanner3DGrid) {
        if (selectedElementsDict.size > 0) {
          selectedElementsDict.forEach(function (selectedPlannerElements, setId) {
            for (var i = 0; i < selectedPlannerElements.length; i++) {
              _this.planner3DGrid.updateUI(plannerUIHandler, selectedPlannerElements[i]);
            }
          });
        } else {
          plannerUIHandler.clear2D3DViewerUI();
        }
      }
      this.UIHandler.updateUI(plannerUIHandler, allPlannedElements, allVisualizedNotPlannedElements, this.curRendering, selectedElementsDict, selectableElements, setAllElementsSelectable, selectedDP, viewPortSize);
    }

    /**
     * This function is called when a new rendering should displayed on the screen.
     * This function handels also the positioning of posnum etc.
     * @param rendering     The rendering to display
     * @param allPlannedElements    All elements in the planning
     * @param selectedElements      All currently selected elements
     * @param renderSize            The size of the rendering
     */
  }, {
    key: "updatePlannerView",
    value: function updatePlannerView(plannerUIHandler, rendering, allPlannedElementsDict, selectedElementsDict, renderSize) {
      var prevImageHasStaticBG = this.curRendering.getHasStaticBackground();
      var curImageHasStaticBG = rendering.getHasStaticBackground();
      if (prevImageHasStaticBG != curImageHasStaticBG) {
        this.onDoShowNav3DChanged(!curImageHasStaticBG);
      }
      this.curRendering = rendering;
      this.update3DImgSrcInView(rendering.getImageForSrc());
      //this.planner3DImg.src = rendering.getImageForSrc();
      //this.planner3DImg.style.display = "";
      if (this.enablePlanner3DGrid) {
        var selectedElement = undefined;
        if (selectedElementsDict.size > 0) {
          selectedElementsDict.forEach(function (allPlannedElements, setId) {
            if (selectedElement == undefined && allPlannedElements.length > 0) selectedElement = allPlannedElements[0];
          });
        }

        //if (selectedElement != undefined) this.planner3DGrid.updateScene(rendering, selectedElement, allPlannedElementsDict, renderSize);
        this.planner3DGrid.updateScene(plannerUIHandler, rendering, selectedElement, allPlannedElementsDict, renderSize);
      }
    }
  }, {
    key: "resetSelectedElementsOnEnterPlannerMode",
    value: function resetSelectedElementsOnEnterPlannerMode() {
      return false;
    }
  }]);
}();

export { Planner3DImage as default };
