const socket = io()

import { pick } from "./modules/utils.js"

import { NOTE, SPACE, RECORDING } from "./settings.js"

import { amsynth } from "./modules/instruments/amsynth.js"
import { duosynth } from "./modules/instruments/duosynth.js"
import { monosynth  } from "./modules/instruments/monosynth.js"
import { membranesynth } from "./modules/instruments/membranesynth.js"
import { plucksynth } from "./modules/instruments/plucksynth.js"

import { reverb } from "./modules/effects/reverb.js"

// Pick an instrument
const instrument = pick([amsynth, duosynth, monosynth, membranesynth, plucksynth])

// A channel to chain instruments and effects
const channel = new Tone.Channel()

// This is a hack to have something running, which makes the reverb work
const pingpong = new Tone.PingPongDelay({delayTime : 2, feedback : 0, wet : 0})

// A filter
const filter = new Tone.Filter({type:"lowpass", frequency:800})

// Chain the channel and effects to the master out
channel.connect(pingpong)
pingpong.connect(reverb)
reverb.connect(Tone.Master)

// Chain instrument to the channel
instrument.connect(channel)

const voice = new Tone.Player("/static/recordings/tts.mp3").connect(channel)
voice.playbackRate = 0.65
voice.loop = true
voice.autostart = false

const noise = new Tone.Noise("brown")

let playloop = undefined
let schedule = undefined
 
const pathway = pick([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])

const play = () => {
  // Determine which of our patterns to play
  switch(pathway) {
    case 0:
      const autoFilter = new Tone.AutoFilter("3m", "200", 3.6).start()
      const cChord = ['C4', 'E4', 'G4', 'B4']
      const dChord = ['D4', 'F4', 'A4', 'C5']
      const gChord = ['B3', 'D4', 'E4', 'A4']

      const piano = new Tone.PolySynth(Tone.Synth, {
        oscillator: {
            partials: [3, 2, 1]
        },
        volume: -9
      }).connect(autoFilter)

      autoFilter.connect(channel)

      const pianoPart = new Tone.Part({
        callback: (time, chord) => {
            piano.triggerAttackRelease(chord, '8n', time)
        },
        events: [
            ['0:0:2', cChord],
            ['0:1', cChord],
            ['0:1:3', dChord],
            ['0:2:2', cChord],
            ['0:3', cChord],
            ['0:3:2', gChord]
        ],
        loop: false,
      })

      const interval = pick(["5m", "6m", "7m"])
      
      schedule = Tone.Transport.scheduleRepeat((time) => {
        pianoPart.stop()
        pianoPart.start()
      }, interval, "0")

      break
    
    case 1:
      playloop = new Tone.Player("/static/recordings/" + RECORDING).connect(channel)
      playloop.loop = true
      playloop.autostart = true
      break
      
    case 2:
      playloop = new Tone.Player("/static/recordings/" + RECORDING).connect(channel)
      playloop.loop = true
      playloop.autostart = true
      break

    case 3:
      playloop = new Tone.Player("/static/recordings/" + RECORDING).connect(channel)
      playloop.loop = true
      playloop.autostart = true
      break

    case 4:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "16n")
      }, SPACE).start(0)
      break

    case 5:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "16n")
      }, SPACE).start(0)
      break

    case 6:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "16n")
      }, SPACE).start(0)
      break

    case 7:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "8n")
      }, SPACE).start(0)
      break

    case 8:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "8n")
      }, SPACE).start(0)
      break

    case 9:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "8n")
      }, SPACE).start(0)
      break
      
    case 10:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "6n")
      }, SPACE).start(0)
      break
    
    case 11:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "6n")
      }, SPACE).start(0)
      break
    
    case 12:
      playloop = new Tone.Loop((time) => {
        instrument.triggerAttackRelease(NOTE, "6n")
      }, SPACE).start(0)
      break

    default:
      // Defaulting
  }
}

(function() {
  socket.on('all_action', () => {
    voice.start()
  })

  socket.on('all_noise', () => {
    voice.stop()
    channel.disconnect(pingpong)
    noise.connect(Tone.Master)
    noise.start()
  })

  socket.on('all_stop', () => {
    noise.stop()
  })

  const flowers = ["🌼", "🌸", "💮", "🌺", "🪷", "🏵️"] 

  const playbutton = document.getElementById('play') 
  
  playbutton.addEventListener('click', () => {
    if (playbutton.className == 'paused') {
      playbutton.className = 'playing'
      playbutton.innerHTML = pick(flowers)

      Tone.context.resume().then(() => {
        Tone.start()
        Tone.Transport.start("+0.1")
      }).then(
        play()
      )
    }
  })
})()
