// sounds
class Sounder {
  constructor(args) {
    this.soundfile = args.soundfile;
    this.gain = args.gain; // (dB)
    this.latitude = args.location[0];
    this.longitude = args.location[1];
    this.spread = args.spread; // (deg)
    this.distmap = args.distmap;
    this.volmin = args.volmin; // (dB)
    this.ramptime = args.ramptime; // (seconds)
  }

  async load() {
    //start sound playback
    this.pv = new Tone.PanVol(0, -99).toDestination();
    this.snd = await AudioImport(this.soundfile); // NOTE: url with spaces didn't work here.
    // this.snd.connect(this.pv).start();
    this.snd.connect(this.pv);
    this.snd.loop = true;
  }

  update() {
    //
    //update sound pan/volume
    //
    // this.ang = getBearing(latitude, longitude, this.latitude, this.longitude);  (deg)
    this.ang = getBearing(latitude, longitude, this.latitude, this.longitude); // (deg)
    this.angerr = (heading - this.ang + 360) % 360;
    this.dist = getDistance(latitude, longitude, this.latitude, this.longitude); // (km)
    //
    this.distvol = map(this.dist, this.distmap[0], this.distmap[1], this.distmap[2], this.distmap[3], true); //(dB)

    // (from Pure Data patch "iamyou", [eqpan2~])
    // arg #1 (inlet #3): width:
    // -width*(1.5) ~ -width/2 -> left fade-in
    // -width/2 ~ width/2 -> cross fading
    // +width/2 ~ width*(1.5) -> right fade-out

    let panleft_start = this.spread * (-1.5);
    let panleft_end = this.spread * (-0.5);
    let panright_start = this.spread * (0.5);
    let panright_end = this.spread * (1.5);

    //left fade-in
    if (this.angerr > panleft_start && this.angerr < panleft_end) {
      this.pv.pan.value = -1; //left-full
      this.pv.volume.rampTo(this.distvol + this.gain + map(this.angerr, panleft_start, panleft_end, this.volmin, 0), this.ramptime)//cross fading; //(dB)
    } else if (this.angerr > panleft_end && this.angerr < panright_start) {
      this.pv.pan.value = map(this.angerr, panleft_end, panright_start, -1, 1); // crossfade
      this.pv.volume.rampTo(this.distvol + this.gain, this.ramptime)//right fade-out; //(dB)
    } else if (this.angerr > panright_start && this.angerr < panright_end) {
      this.pv.pan.value = 1; //right-full
      this.pv.volume.rampTo(this.distvol + this.gain + map(this.angerr, panright_start, panright_end, 0, this.volmin), this.ramptime)//slience; //(dB)
    } else {
      this.pv.volume.rampTo(-99, 10); //(dB)
    }
  }

  draw() {
    //draw sound location
  }
}

//
class RadioSounder extends Sounder {

  //do nothing
  async load() {
    ;
  }

  link(audiotag) {
    //start sound playback
    this.pv = new Tone.PanVol(0, -99).toDestination();
    let stream = Tone.context.createMediaElementSource(audiotag);
    this.snd = Tone.context.createGain();
    stream.connect(this.snd);
    console.log(stream);
    console.log(this.snd);
    console.log(this.pv);
    // this.snd.connect(this.pv.input.input);  a hack ...
    this.snd.gain.value = 1;
    this.snd.connect(Tone.context.destination);
  }
}

//p5
class Compass {
  constructor(size, colors) {
    this.size = size;
    this.colors = colors;
    this.heading = 0;
  }

  draw() {
    push();
    //
    scale(this.size);
    //
    translate(0.5, 0.5);
    //
    noStroke();
    //
    fill(this.colors[0]);
    circle(0, 0, 0.9);
    //
    fill(this.colors[1]);
    rotate(this.heading * -1);
    quad(0.1, 0.2, 0, -0.4, -0.1, 0.2, 0, 0.1);
    //
    fill(this.colors[2]);
    circle(0, 0, 0.05);
    //
    pop();
  }
}
