import * as Three from 'three';
import React from 'react';

const WIDTH = 50;
const DEPTH = 30;
const HEIGHT = 80;


const textureLoader = new Three.TextureLoader();
const frontTexture = textureLoader.load(require('./naspofront.png'));

let red ,grey ,black , mesh3Texture


function makeObjectMaxLOD(){

  let naspo = new Three.Mesh();

  let roundedRectShape = new Three.Shape();

  let x=0;
  let y=0;
  let radius = 0.1;
  let height = 1.2;
  let width = 0.8;
  let depth = 0.6;

  roundedRectShape.moveTo( x, y + radius );
  roundedRectShape.lineTo( x, y + height - radius );
  roundedRectShape.quadraticCurveTo( x, y + height, x + radius, y + height );
  roundedRectShape.lineTo( x + width - radius, y + height) ;
  roundedRectShape.quadraticCurveTo( x + width, y + height, x + width, y + height - radius );
  roundedRectShape.lineTo( x + width, y + radius );
  roundedRectShape.quadraticCurveTo( x + width, y, x + width - radius, y );
  roundedRectShape.lineTo( x + radius, y );
  roundedRectShape.quadraticCurveTo( x, y, x, y + radius );

  let extrudeSettings = {
    steps: 2,
    depth: depth/3,
    bevelEnabled: false,
    bevelThickness: 1,
    bevelSize: 1,
    bevelSegments: 1
  };

  let geometryBody = new Three.ExtrudeGeometry( roundedRectShape, extrudeSettings );
  let mesh = new Three.Mesh( geometryBody, red ) ;
  mesh.position.set(0.1,1.1,0.1);
  naspo.add(mesh);

  let geometryBox = new Three.BoxGeometry(0.95,1.05,0.2);
  let mesh1 = new Three.Mesh( geometryBox, red );
  mesh1.position.set(0.5,1.7,0.2);
  naspo.add(mesh1);

  let geometryPlane = new Three.PlaneGeometry(0.6,0.9);
  let mesh3 = new Three.Mesh( geometryPlane, mesh3Texture);
  mesh3.position.set(0.5,1.7,0.31);
  naspo.add(mesh3);

  let cylinderGeometry1 = new Three.CylinderGeometry(0.05,0.05,0.025,80,80);
  let handle_p1 = new Three.Mesh(cylinderGeometry1,grey);
  handle_p1.position.set(0.17,1.7,0.3);
  handle_p1.rotation.x=Math.PI/2;
  naspo.add(handle_p1);

  let cylinderGeometry2 = new Three.CylinderGeometry(0.051,0.051,0.05,80,80,true);
  black.side=Three.DoubleSide;
  let handle_p2 = new Three.Mesh(cylinderGeometry2,black);
  handle_p2.position.set(0.17,1.7,0.31);
  handle_p2.rotation.x=Math.PI/2;
  naspo.add(handle_p2);

  let geometry = new Three.BoxGeometry(0.1,0.02,0.02);
  let handle_p3 = new Three.Mesh( geometry,black  );
  handle_p3.position.set(0.17,1.7,0.32);
  naspo.add(handle_p3);

  let cylinderGeometry4 = new Three.CylinderGeometry(0.015,0.015,0.1,80,80);
  let pivot1 = new Three.Mesh(cylinderGeometry4,black);
  pivot1.position.set(0.99,1.9,0.28);
  naspo.add(pivot1);

  let cylinderGeometry5 = new Three.CylinderGeometry(0.015,0.015,0.1,80,80);
  let pivot2 = new Three.Mesh(cylinderGeometry5,black);
  pivot2.position.set(0.99,1.4,0.28);
  naspo.add(pivot2);

  let roundedRectShape2 = new Three.Shape();

  let width2=1.05;
  let height2=1.3;
  let radius2=0.1;

  roundedRectShape2.moveTo( x, y + radius2 );
  roundedRectShape2.lineTo( x, y + height2 - radius2 );
  roundedRectShape2.quadraticCurveTo( x, y + height2, x + radius2, y + height2 );
  roundedRectShape2.lineTo( x + width2 - radius2, y + height2) ;
  roundedRectShape2.quadraticCurveTo( x + width2, y + height2, x + width2, y + height2 - radius2 );
  roundedRectShape2.lineTo( x + width2, y + radius2 );
  roundedRectShape2.quadraticCurveTo( x + width2, y, x + width2 - radius2, y );
  roundedRectShape2.lineTo( x + radius2, y );
  roundedRectShape2.quadraticCurveTo( x, y, x, y + radius2 );

  let extrudeSettings2 = {
    steps: 2,
    depth: depth,
    bevelEnabled: false,
    bevelThickness: 1,
    bevelSize: 1,
    bevelSegments: 1
  };

  let geometry2 = new Three.ExtrudeGeometry( roundedRectShape2, extrudeSettings2 );
  let mesh2 = new Three.Mesh( geometry2, red ) ;
  mesh2.position.set(0,1.05,-0.33);
  naspo.add(mesh2);

  return naspo
}

function makeObjectMiddleLOD(){

  let naspo = new Three.Mesh();

  let roundedRectShape2 = new Three.Shape();

  let x=0;
  let y=0;
  let width2=1.05;
  let height2=1.3;
  let radius2=0.1;
  let depth=0.6;

  roundedRectShape2.moveTo( x, y + radius2 );
  roundedRectShape2.lineTo( x, y + height2 - radius2 );
  roundedRectShape2.quadraticCurveTo( x, y + height2, x + radius2, y + height2 );
  roundedRectShape2.lineTo( x + width2 - radius2, y + height2) ;
  roundedRectShape2.quadraticCurveTo( x + width2, y + height2, x + width2, y + height2 - radius2 );
  roundedRectShape2.lineTo( x + width2, y + radius2 );
  roundedRectShape2.quadraticCurveTo( x + width2, y, x + width2 - radius2, y );
  roundedRectShape2.lineTo( x + radius2, y );
  roundedRectShape2.quadraticCurveTo( x, y, x, y + radius2 );

  let extrudeSettings2 = {
    steps: 2,
    depth: depth,
    bevelEnabled: false,
    bevelThickness: 1,
    bevelSize: 1,
    bevelSegments: 1
  };

  let geometry2 = new Three.ExtrudeGeometry( roundedRectShape2, extrudeSettings2 );
  let mesh2 = new Three.Mesh( geometry2, red ) ;
  mesh2.position.set(0,1.05,-0.33);
  naspo.add(mesh2);

  let geometryBox = new Three.BoxGeometry(0.95,1.05,0.2);
  let mesh1 = new Three.Mesh( geometryBox, red );
  mesh1.position.set(0.5,1.7,0.2);
  naspo.add(mesh1);

  let geometryPlane = new Three.PlaneGeometry(0.6,0.9);
  let mesh3 = new Three.Mesh( geometryPlane, mesh3Texture);
  mesh3.position.set(0.5,1.7,0.31);
  naspo.add(mesh3);

  return naspo;
}

function makeObjectMinLOD(){

  let naspo = new Three.Mesh();

  let roundedRectShape2 = new Three.Shape();

  let x=0;
  let y=0;
  let width2=1.05;
  let height2=1.3;
  let radius2=0.1;
  let depth=0.6;

  roundedRectShape2.moveTo( x, y + radius2 );
  roundedRectShape2.lineTo( x, y + height2 - radius2 );
  roundedRectShape2.quadraticCurveTo( x, y + height2, x + radius2, y + height2 );
  roundedRectShape2.lineTo( x + width2 - radius2, y + height2) ;
  roundedRectShape2.quadraticCurveTo( x + width2, y + height2, x + width2, y + height2 - radius2 );
  roundedRectShape2.lineTo( x + width2, y + radius2 );
  roundedRectShape2.quadraticCurveTo( x + width2, y, x + width2 - radius2, y );
  roundedRectShape2.lineTo( x + radius2, y );
  roundedRectShape2.quadraticCurveTo( x, y, x, y + radius2 );

  let extrudeSettings2 = {
    steps: 2,
    depth: depth,
    bevelEnabled: false,
    bevelThickness: 1,
    bevelSize: 1,
    bevelSegments: 1
  };

  let geometry2 = new Three.ExtrudeGeometry( roundedRectShape2, extrudeSettings2 );
  let mesh2 = new Three.Mesh( geometry2, red ) ;
  mesh2.position.set(0,1.05,-0.33);
  naspo.add(mesh2);

  return naspo;
}



export default {
  name: "naspo",
  prototype: "items",

  info: {
    tag: ['furnishings', 'metal'],
    title: "naspo",
    description: "naspo",
    image: require('./naspo.png')
  },
  properties: {
    altitude: {
      label: "altitude",
      type: "length-measure",
      defaultValue: {
        length: 60,
        unit: 'cm'
      }
    },

    
    associate: {
      label: "Associate",
      type: "associate",
      defaultValue:{
        category: "-",
        thing: "-",
        thingName: "",
        popUp: "model",
        hoverColor: "#ffffff"
      }
    }
  },

  render2D: function (element, layer, scene) {

    let angle = element.rotation + 90;

    let textRotation = 0;
    if (Math.sin(angle * Math.PI / 180) < 0) {
      textRotation = 180;
    }

    return (
      <g transform={`translate(${-WIDTH / 2},${-DEPTH / 2})`}>
        <rect key="1" x="0" y="0" width={WIDTH} height={DEPTH}
              style={{stroke: element.selected ? '#0096fd' : '#000', strokeWidth: "2px", fill: "#ff0000"}}/>
        <text key="2" x="0" y="0"
              transform={`translate(${WIDTH / 2}, ${DEPTH / 2}) scale(1,-1) rotate(${textRotation})`}
              style={{textAnchor: "middle", fontSize: "11px"}}>
          {element.type}
        </text>
        {(element.properties.get("associate"))&&<text key='3' x='0' y='10'
              transform={`translate(${WIDTH / 2}, ${DEPTH / 2}) scale(1,-1) rotate(${textRotation})`}
              style={{textAnchor: 'middle', fontSize: '11px', fill: "red"}}>
          {element.properties.get("associate").get("thingName")}
        </text>}
      </g>
    )
  },

  render3D: function (element, layer, scene) {

    let newAltitude = element.properties.get('altitude').get('length');

    /**************** LOD max ***********************/

    if(element.get("selected")){

      red = new Three.MeshLambertMaterial({color: "green", opacity: 0.8});
      grey = new Three.MeshLambertMaterial({color: "green", opacity: 0.8});
      black = new Three.MeshLambertMaterial({color: "green", opacity: 0.8});
      mesh3Texture = new Three.MeshLambertMaterial({color: "green", opacity: 0.8});}

    else if(element.getIn(["properties", "associate", "thing"])!="-"){
      
      red = new Three.MeshBasicMaterial({color : element.getIn(["properties", "associate", "hoverColor"])});
      grey = new Three.MeshBasicMaterial({color : element.getIn(["properties", "associate", "hoverColor"])});
      black = new Three.MeshBasicMaterial({color : element.getIn(["properties", "associate", "hoverColor"])});
      mesh3Texture = new Three.MeshBasicMaterial({color : element.getIn(["properties", "associate", "hoverColor"])});

    }else{      
      red = new Three.MeshPhongMaterial({color: 0xAA0000} );
      grey = new Three.MeshLambertMaterial({color:0xAAAAAA});
      black = new Three.MeshLambertMaterial({color:0x000000});
      mesh3Texture = new Three.MeshPhongMaterial({map:frontTexture, transparent:true})
    }

    
    const objectMaxLOD = makeObjectMaxLOD();
    const objectMiddleLOD = makeObjectMiddleLOD();
    const objectMinLOD = makeObjectMinLOD();

    let naspoMaxLOD = new Three.Object3D();
    naspoMaxLOD.add(objectMaxLOD.clone());

    let valuePosition = new Three.Box3().setFromObject(naspoMaxLOD);

    let deltaX = Math.abs(valuePosition.max.x - valuePosition.min.x);
    let deltaY = Math.abs(valuePosition.max.y - valuePosition.min.y);
    let deltaZ = Math.abs(valuePosition.max.z - valuePosition.min.z);

    naspoMaxLOD.rotation.y+= Math.PI;
    naspoMaxLOD.position.x+= WIDTH/2;
    naspoMaxLOD.position.y+= -HEIGHT/1.3 + newAltitude;
    naspoMaxLOD.scale.set(WIDTH / deltaX, HEIGHT / deltaY, DEPTH / deltaZ);


    /**************** LOD middle ***********************/

    let naspoMiddleLOD = new Three.Object3D();
    naspoMiddleLOD.add(objectMiddleLOD.clone());

    naspoMiddleLOD.rotation.y+= Math.PI;
    naspoMiddleLOD.position.x+= WIDTH/2;
    naspoMiddleLOD.position.y+= -HEIGHT/1.3 + newAltitude;
    naspoMiddleLOD.scale.set(WIDTH / deltaX, HEIGHT / deltaY, DEPTH / deltaZ);

    /**************** LOD min ***********************/

    let naspoMinLOD = new Three.Object3D();
    naspoMinLOD.add(objectMinLOD.clone());

    naspoMinLOD.rotation.y+= Math.PI;
    naspoMinLOD.position.x+= WIDTH/2;
    naspoMinLOD.position.y+= -HEIGHT/1.3 + newAltitude;
    naspoMinLOD.scale.set(WIDTH / deltaX, HEIGHT / deltaY, DEPTH / deltaZ);

    /*** add all Level of Detail ***/

    let lod = new Three.LOD();

    lod.addLevel(naspoMaxLOD, 200);
    lod.addLevel(naspoMiddleLOD, 900);
    lod.addLevel(naspoMinLOD, 1200);
    lod.updateMatrix();
    lod.matrixAutoUpdate = false;

    if (element.selected) {
      let bbox = new Three.BoxHelper(lod, "green");
      bbox.material.linewidth = 5;
      bbox.renderOrder = 1000;
      bbox.material.depthTest = false;
      lod.add(bbox);
    }

    return Promise.resolve(lod);
  }

};

