const Signal = require('signals')
const Vec3 = require('pex-math/Vec3')
const Mat4 = require('pex-math/Mat4')

function Morph (opts) {
  this.type = 'Morph'
  this.entity = null
  this.targets = opts.targets || []
  this.weights = opts.weights || []
  this.changed = new Signal()
  this.set(opts)
}

Morph.prototype.init = function (entity) {
  this.entity = entity
  let geom = this.entity.getComponent('Geometry')
  this.originalPositions = geom.positions.slice(0)
}

Morph.prototype.set = function (opts) {
  Object.assign(this, opts)
  Object.keys(opts).forEach((prop) => this.changed.dispatch(prop))
}

Morph.prototype.update = function () {
  let geom = this.entity.getComponent('Geometry')
  // this.targets.forEach((target, i) => {
  //   let weight = this.weights[i]
  //   let newGeom = this.originalPositions.map((pos, k) => {
  //     let targetVertex = target[k]
  //     let morphedVertex = (targetVertex - pos) * weight
  //     morphedVertex += pos
  //     return morphedVertex
  //   })
  //   geom.set({
  //     positions: newGeom
  //   })
  // })
  let newGeom = this.originalPositions.map((pos, i) => {
    let newPos = 0
    let originalPos = this.originalPositions[i]
    this.targets.forEach((target, k) => {
      let weight = this.weights[k]
      let targetVertex = target[i]
      let morphedVertex = (targetVertex - originalPos) * weight
      newPos += morphedVertex
    })
    newPos += originalPos
    return newPos
  })
  geom.set({
    positions: newGeom
  })
}

module.exports = function createMorph (opts) {
  return new Morph(opts)
}

const Signal = require('signals')

function Morph (opts) {
  this.type = 'Morph'
  this.entity = null
  this.dirty = false
  this.targets = opts.targets || []
  this.weights = opts.weights || []
  this.changed = new Signal()
  this.set(opts)
}

Morph.prototype.init = function (entity) {
  this.entity = entity
  let geom = this.entity.getComponent('Geometry')
  this.originalPositions = geom.positions.slice(0)
}

Morph.prototype.set = function (opts) {
  Object.assign(this, opts)
  Object.keys(opts).forEach((prop) => this.changed.dispatch(prop))
  this.dirty = true
}

Morph.prototype.update = function () {
  if (!this.dirty) return
  this.dirty = false

  let geom = this.entity.getComponent('Geometry')
  let newGeom = this.originalPositions.map((pos, i) => {
    let newPos = 0
    if (pos.length) {
      newPos = [0, 0, 0]
    }
    let originalPos = this.originalPositions[i]
    this.targets.forEach((target, k) => {
      let weight = this.weights[k]
      let targetVertex = target[i]
      if (pos.length) {
        newPos[0] += targetVertex[0] * weight
        newPos[1] += targetVertex[1] * weight
        newPos[2] += targetVertex[2] * weight
      } else {
        newPos += targetVertex * weight
      }
    })
    if (pos.length) {
      newPos[0] += originalPos[0]
      newPos[1] += originalPos[1]
      newPos[2] += originalPos[2]
    } else {
      newPos += originalPos
    }
    return newPos
  })
  geom.set({
    positions: newGeom
  })
}

module.exports = function createMorph (opts) {
  return new Morph(opts)
}

Update morph on demand and add support for Vec3 vertices