import Controller from '../Controller';
import NumberSetting from '../Settings/NumberSetting';

export interface EnvelopeSettings {
  attack: NumberSetting;
  decay: NumberSetting;
  sustain: NumberSetting;
  release: NumberSetting;
}

export default class EnvelopeController extends Controller<number, EnvelopeSettings> {
  releaseTime: number | null = null;
  effectiveSustain: number = 0;
  getDefaultSettings() {
    return {
      attack: new NumberSetting(0),
      decay: new NumberSetting(0),
      sustain: new NumberSetting(1),
      release: new NumberSetting(0)
    };
  }

  on() {
    this.time = 0;
    this.releaseTime = null;
  }

  off() {
    this.releaseTime = this.time;
  }

  fullyReleased () {
    return this.releaseTime !== null && (this.time - this.releaseTime) >= this.settings.release.value;
  }

  calculateValue() {
    if (this.releaseTime !== null) {
      if (this.settings.release.value === 0) return 0;
      return Math.max(0, this.effectiveSustain * (1 - ((this.time - this.releaseTime) / this.settings.release.value)));
    } else if (this.time < this.settings.attack.value) {
      this.effectiveSustain = (this.time / this.settings.attack.value);
      return this.effectiveSustain;
    } else if (this.time < (this.settings.attack.value + this.settings.decay.value)) {
      this.effectiveSustain = 1 + ((this.time - this.settings.attack.value) / (this.settings.decay.value)) * (this.settings.sustain.value - 1);
      return this.effectiveSustain;
    } else {
      this.effectiveSustain = this.settings.sustain.value;
      return this.effectiveSustain;
    }
  }
}
