<!--suppress HtmlFormInputWithoutLabel -->
<template>
    <div id="app">
        <h1>noisemaker</h1>
        <div class="channels-wrapper">
            <div class="channels">
                <template v-for="i in N_CHANNELS">
                    <Channel :name="names[i - 1]" :url="urls[i - 1]" :volume="volumes[i-1]"
                             :key="i"
                             class="channel" ref="channels"/>
                </template>
            </div>
            <div class="channel-urls">
                <div class="url-input" v-for="i in N_CHANNELS">
                    <label :for="`url-input-${names[i-1]}`">
                        {{names[i - 1]}}
                    </label>
                    <input :id="`url-input-${names[i-1]}`" type="text" v-model="urls[i - 1]"/>
                </div>
            </div>
        </div>
        <div class="controls">
            <button @click="start">START</button>
        </div>
    </div>
</template>

<!--suppress JSUnusedLocalSymbols, JSMethodCanBeStatic -->
<script lang="ts">
import {Component, Vue} from "vue-property-decorator";
import Channel from "@/components/Channel.vue";

@Component({
  components: {
    Channel,
  },
})
export default class App extends Vue {
  private readonly N_CHANNELS = 6;
  private readonly LFO_PERIOD = 30_000;
  private readonly LFO_DEPTH = 33;
  private readonly LFO_OFFSET = 66;

  private names = ["alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda", "mu"];
  private urls = Array(this.N_CHANNELS).fill("");
  private volumes = Array(this.N_CHANNELS).fill(50);
  private animateVolumeStart?: Date;
  private animateVolumeInterval?: number;

  private defaultMedia = [
    "https://www.youtube.com/watch?v=q76bMs-NwRk",
  ];

  private mounted() {
    this.defaultMedia.forEach((url, idx) => {
      this.$set(this.urls, idx, url);
    });
  }

  private start() {
    (this.$refs.channels as Channel[]).forEach((channel) => {
      channel.start();
      this.animateVolume();
    });
  }

  private animateVolume() {
    clearInterval(this.animateVolumeInterval);
    this.animateVolumeStart = new Date();
    this.animateVolumeInterval = setInterval(() => {
      if (this.animateVolumeStart) {
        const delta = new Date().getTime() - this.animateVolumeStart.getTime();

        this.volumes = [...Array(this.N_CHANNELS).keys()]
          .map((idx) => {
            const offset = idx * (1 / this.N_CHANNELS);
            const progress = delta / this.LFO_PERIOD + offset;
            return Math.sin(progress * 2 * Math.PI) * this.LFO_DEPTH + this.LFO_OFFSET;
          });
      }
    }, 1000 / 60);
  }
}
</script>

<style>
html, body {
    font-family: monospace;
    font-size: 14px;
    padding: 0;
    margin: 0;
}

input[type="text"] {
    font-family: monospace;
    padding: 4px;
    background: white;
    border: 1px solid black;
}

button {
    background: white;
    border: 1px solid black;
    box-shadow: 2px 2px #272727;
    font-size: 1.5rem;
}

h1 {
    font-size: 20px;
    margin: 1rem 0;
    font-weight: normal;
    text-transform: uppercase;
    letter-spacing: 15px;
}

#app {
    display: flex;
    flex-direction: column;
    align-items: center;
}


.channels-wrapper {
    display: flex;
    width: 80%;
}

.channels {
    display: flex;
    padding: 0 1rem;
}

.channel {
    margin: 0 1rem;
}

.channel-urls {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    width: 100%;
}

.url-input {
    display: flex;
    width: 100%;
    align-items: center;
}

.url-input label {
    display: inline-block;
    width: 64px;
    text-align: center;
}

.url-input input {
    flex-grow: 1;
}

.controls {
    padding: 2rem 0;
}
</style>
