//Base part
//Where all parts are inherited from
//Uses on main and sync

const PartBase = function (par) {
  this.elapsed = 0;
  this.startTime = false;
  this.deltaFrame = 0;
  this.index = TDEMO.getId();
  this.postIndex = this.index + 1;

  //console.log("Part renderer in index: ", this.index);

  const size = TDEMO.MAIN.getRendererSize();
  this.width = size[0];
  this.height = size[1];
  const aspect = this.width / this.height;

  const p = par || {};

  this.near = p.near !== undefined ? p.near : 0.1;
  this.far = p.far !== undefined ? p.far : 2000;

  this.scene = p.scene !== undefined ? p.scene : new THREE.Scene();
  this.camera =
    p.camera !== undefined
      ? p.camera
      : new THREE.PerspectiveCamera(50, aspect, this.near, this.far);
  this.lens = {
    fl: 10,
    fg: 35,
  };

  if (this.camera.isPerspectiveCamera) {
    this.camera.filmGauge = this.lens.fg;
    this.camera.setFocalLength(this.lens.fl);
  }
  this.camera.updateProjectionMatrix();

  this.scene.add(this.camera);

  this.renderPass =
    p.rendererPass !== undefined
      ? p.rendererPass
      : new THREE.RenderPass(this.scene, this.camera);
  this.renderPass.enabled = false;
  TDEMO.MAIN.getComposer().insertPass(this.renderPass, this.index);

  this.bloom = false;

  this.dof = false;
  this.dcopy = false;

  this.edge = false;

  this.vblur = false;
  this.hblur = false;
};

PartBase.prototype.setBloom = function (amount) {
  if (this.bloom === false) {
    this.bloom = new THREE.BloomPass(amount, 25, 4, this.width);
    this.bloom.renderToScreen = true;
    this.bloom.needsSwap = false;
    this.bloom.clear = false;
    TDEMO.MAIN.getComposer().insertPass(this.bloom, this.postIndex);
    ++this.postIndex;
    this.bloom.enabled = false;
  }
};

PartBase.prototype.setDoF = function (par) {
  const p = par || {};
  const focus = p.focus !== undefined ? p.focus : 1.0;
  const width = p.width !== undefined ? p.width : this.width;
  const height = p.height !== undefined ? p.height : this.height;
  const maxblur = p.maxblur !== undefined ? p.maxblur : 1.0;
  const aperture = p.aperture !== undefined ? p.aperture : 0.025;
  const camera = p.camera !== undefined ? p.camera : this.camera;

  if (this.dof === false) {
    this.dof = new THREE.BokehPass(this.scene, camera, {
      focus: focus,
      maxblur: maxblur,
      aperture: aperture,
      width: width,
      height: height,
    });
    this.dof.needsSwap = true;
    this.dof.renderToScreen = false;
    this.dof.clear = false;
    TDEMO.MAIN.getComposer().insertPass(this.dof, this.postIndex);
    ++this.postIndex;

    this.dcopy = new THREE.ShaderPass(THREE.CopyShader);
    TDEMO.MAIN.getComposer().insertPass(this.dcopy, this.postIndex);
    ++this.postIndex;

    this.dof.enabled = false;
    this.dcopy.enabled = false;
  }
};

PartBase.prototype.setEdgeDetection = function () {
  if (this.edge === false) {
    this.edge = new THREE.ShaderPass(THREE.EdgeShader2);
    this.edge.uniforms["resolution"].value = new THREE.Vector2(
      this.width,
      this.height
    );
    TDEMO.MAIN.getComposer().insertPass(this.edge, this.postIndex);
    ++this.postIndex;

    this.edge.enabled = false;
  }
};

PartBase.prototype.setHorizontalBlur = function (amount) {
  if (this.hblur === false) {
    this.hblur = new THREE.ShaderPass(THREE.HorizontalBlurShader);
    this.hblur.uniforms["h"].value = amount / this.width;
    TDEMO.MAIN.getComposer().insertPass(this.hblur, this.postIndex);
    ++this.postIndex;

    this.hblur.enabled = false;
  }
};

PartBase.prototype.setVerticalBlur = function (amount) {
  if (this.vblur === false) {
    this.vblur = new THREE.ShaderPass(THREE.VerticalBlurShader);
    this.vblur.uniforms["v"].value = amount / this.height;
    TDEMO.MAIN.getComposer().insertPass(this.vblur, this.postIndex);
    ++this.postIndex;

    this.vblur.enabled = false;
  }
};

//prepare is called just before first rendering
PartBase.prototype.prepare = function (elapsedTime, rtt) {
  this.startTime = elapsedTime;
  this.renderPass.enabled = true;

  if (this.bloom !== false) {
    this.bloom.enabled = true;
    //console.log("Bloom enabled from part : ", this.index);
  }
  if (this.dof !== false) {
    this.dof.enabled = true;
    this.dcopy.enabled = true;
    //console.log("DoF enabled from part : ", this.index);
  }
  if (this.edge !== false) {
    this.edge.enabled = true;
    //console.log("Edge detection enabled from part : ", this.index);
  }
  if (this.hblur !== false) {
    this.hblur.enabled = true;
    //console.log("Horizontal blur enabled from part : ", this.index);
  }
  if (this.vblur !== false) {
    this.vblur.enabled = true;
    //console.log("Vertical blur enabled from part : ", this.index);
  }
};

PartBase.prototype.finish = function () {
  this.renderPass.enabled = false;
  TDEMO.MAIN.getRenderer().clear();

  if (this.bloom !== false) {
    this.bloom.enabled = false;
    //console.log("Bloom disabled from part : ", this.index);
  }
  if (this.dof !== false) {
    this.dof.enabled = false;
    this.dcopy.enabled = false;
    //console.log("DoF disabled from part : ", this.index);
  }
  if (this.edge !== false) {
    this.edge.enabled = false;
    //console.log("Edge detection disabled from part : ", this.index);
  }
  if (this.hblur !== false) {
    this.hblur.enabled = false;
    //console.log("Horizontal blur disabled from part : ", this.index);
  }
  if (this.vblur !== false) {
    this.vblur.enabled = false;
    //console.log("Vertical blur disabled from part : ", this.index);
  }
};

//rendering function for rendering the scene to framebuffer otherwise the scene is rendered just with the composer
PartBase.prototype.render = function (renderer, rtt) {
  renderer.render(this.scene, this.camera, rtt);
};

//animation
PartBase.prototype.animate = function (elapsedTime, delta, animateCamera) {
  if (this.startTime !== false) {
    this.elapsed = elapsedTime - this.startTime;
  } else {
    this.elapsed = 0;
  }
  this.deltaFrame = delta;

  if (animateCamera) {
    //Animating camera propertis
    this.near = TDEMO.SYNC.getNear();
    this.far = TDEMO.SYNC.getFar();

    this.camera.near = this.near;
    this.camera.far = this.far;

    if (this.camera.isPerspectiveCamera) {
      this.lens = TDEMO.SYNC.getLens();
      this.camera.filmGauge = this.lens.fg;
      this.camera.setFocalLength(this.lens.fl);
    }
    this.camera.updateProjectionMatrix();

    //Animating camera position only when animateCamera is set to true
    var camp = TDEMO.SYNC.getCameraPosition();
    this.camera.position.x = camp.x;
    this.camera.position.y = camp.y;
    this.camera.position.z = camp.z;

    var camr = TDEMO.SYNC.getCameraRotation();
    this.camera.rotation.x = camr.x;
    this.camera.rotation.y = camr.y;
    this.camera.rotation.z = camr.z;
  }
};

//--------------------------------------------------
// PROTOTYPAL INHERITANCE FUNCTION
//--------------------------------------------------
PartBase.prototype.inheritance = function () {
  function PartBasePrototype() {}
  PartBasePrototype.prototype = this;
  var created = new PartBasePrototype();
  return created;
};
