const tau = 2*Math.PI

let vm = new Vue({
  data(){
    return{
      canvas: null,
      context: null,
      ogglist: [
        og00, og01, og02, og03, og04, og05,
        og06, og07, og08, og09, og10, og11,
        og12, og13, og14, og15, og16, og17,
        og18, og19, og20, og21, og22, og23,
        og24, og25, og26, og27, og28, og29,
        og30, og31, og32, og33, og34, og35,
      ],
      bwKeys: [0,1,0,1,0,0,1,0,1,0,1,0],
      whiteKeyWidth: 30,
      whiteKeyHeight: 100,
      blackKeyWidth: 16,
      blackKeyHeight: 60,
      lastKey: 47,
      whiteKeys: {
        0:0 ,2:1,4:2,5:3,7:4,9:5,11:6,
        12:7,14:8,16:9,17:10,19:11,21:12,23:13,
        24:14,26:15,28:16,29:17,31:18,33:19,35:20,
        36:21,38:22,40:23,41:24,43:25,45:26,47:27,
        48:28,50:29,52:30,53:31,55:32,57:33,59:34
      },
      keyColors: [
        0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0
      ],
      rootKey: 0,
      domKeyColor: '#000000',
      colScale: "#25465d",
      colInversion: "#ffbaba",
      colChord: "#ef3932",
      colKey: "#e9d2d2",
      colLine: "#e9d2d2",
      scale: [0,2,4,5,7,9,11],
      currentChord: [],
      mode: 0,
      modes: [
        [0,2,4,5,7,9,11], // Ionian
        [0,2,3,5,7,9,10], // Dorian
        [0,1,3,5,7,8,10], // Phrygian
        [0,2,4,6,7,9,11], // Lydian
        [0,2,4,5,7,9,10], // Mixolydian
        [0,2,3,5,7,8,10], // Aeolian
        [0,1,3,5,6,8,10], // Locrian
        [0,2,3,6,7,9,10], // Misheberak
        [0,1,4,5,7,8,10], // Freygish
        [0,2,3,6,7,8,11], // Hungarian Minor
        [0,3,4,6,7,9,10], // Hungarian Major
        [0,1,4,5,6,8,11], // Persian
        [0,2,4,6,8,10] // Whole tone
        ],
      modesdegs: [
        ['I','ii','iii','IV','V','vi','vii°'], // Ionian 
        ['i','ii','III','IV','v','vi°','VII'], // Dorian 
        ['i','II','III','iv','v°','VI','vii'], // Phrygian 
        ['I','II','iii','iv°','V','vi','vii'], // Lydian 
        ['I','ii','iii°','IV','v','vi','VII'], // Mixolidian 
        ['i','ii°','III','iv','v','VI','VII'], // Aeolian 
        ['i°','II','iii','iv','V','VI','vii'], // Locrian 
        ['i','II','III','iv°','v','vi°','VII⁺'], // Misheberak 
        ['I','II','iii°','iv','v°','vi⁺','vi'], // Freygish 
        ['i','IIb5','III⁺','iv°b3','V','VI','vii'], // Hungarian Minor
        ['I','ii°','iii°','iv°','II','vi°','ii'], // Hungarian Major
        ['Ib5','II','IIIsus2','iv','Vsus4','VI⁺','vii°b3'], // Persian
        ['WH','A','T','E','V','ER','↓?'], // Whole tone

      ],
      baseNoteList: [
        'C','Db','D','Eb','E','F',
        'F#','G','Ab','A','Bb','B'
      ],
      noteList: [
        'C','Db','D','Eb','E','F',
        'F#','G','Ab','A','Bb','B'
      ],
      noteScale: ['C','D','E','F','G','A','B'],
      flatSharpList: [
        ['C','C']  ,['C#','Db'],['D','D'],
        ['D#','Eb'],['E','E']  ,['E#','F'],
        ['F#','Gb'],['G','G']  ,['G#','Ab'],
        ['A','A'],['A#','Bb']  ,['B','Cb']
      ],
      flatList: [
        'C','Db','D',
        'Eb','E','F',
        'Gb','G','Ab',
        'A','Bb','Cb'
      ],
      sharpList: [
        'C','C#','D',
        'D#','E','E#',
        'F#','G','G#',
        'A','A#','B'
      ],
      chords: {
        'M':      [0,4,7],
        'M6':     [0,4,7,9],
        'M7m':    [0,4,7,10],
        'M7M':    [0,4,7,11],
        'M9':     [0,4,7,10,14],
        'M69':    [0,4,7,9,14],
        'Madd2':  [0,2,4,7],
        'Madd9':  [0,4,7,14],
        'm':      [0,3,7],
        'm6':     [0,3,7,9],
        'm7m':    [0,3,7,10],
        'm7M':    [0,3,7,11],
        'm9':     [0,3,7,10,14],
        'm69':    [0,3,7,9,14],
        'madd2':  [0,2,3,7],
        'madd9':  [0,3,7,14],
        'sus2':   [0,2,7],
        'sus26':  [0,2,7,9],
        'sus27':  [0,2,7,10],
        'sus27M': [0,2,7,11],
        'sus4':   [0,5,7],
        'sus46':  [0,5,7,9],
        'sus47':  [0,5,7,10],
        'sus47M': [0,5,7,11],
        'dimb3':  [0,2,6],
        'dim':    [0,3,6],
        'dim7':   [0,3,6,9],
        'b5':     [0,4,6],
        'aug':    [0,4,8],
        'aug7':   [0,4,8,10],
        'p4':     [0,5],
        'TT':     [0,6],
        'p5':     [0,7],
        'M7f5':   [0,4,6,10],
        'M7s5':   [0,4,8,10]
      }
    }
  },
  methods:{
    sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    },
    drawKey(keyNumber) {
      var keyColor = this.bwKeys[keyNumber%12]
      var keyIndex
      var x0, x1, xc
      var circleXOffset, circleYOffset
      var keyHeight

      this.ctx.beginPath();
      
      if (keyColor == 0){
        keyIndex = this.whiteKeys[keyNumber.toString(10)]
        x0 = this.whiteKeyWidth * keyIndex + 2
        x1 = x0 + this.whiteKeyWidth - 4
        keyHeight = this.whiteKeyHeight

        this.ctx.fillStyle = "#d5d5d5";
        circleYOffset = 85;
        circleXOffset = 13;

      } else {
        keyIndex = this.whiteKeys[(keyNumber-1).toString(10)]
        x0 = this.whiteKeyWidth * (keyIndex + 1)
        x0 -= (this.blackKeyWidth / 2)
        x1 = x0 + this.blackKeyWidth
        xc = x1 - x0;
        keyHeight = this.blackKeyHeight

        this.ctx.fillStyle = "#000000";
        circleYOffset = 50;
        circleXOffset = 8;
      }

      this.ctx.moveTo(x0,0)
      this.ctx.lineTo(x1,0)
      this.ctx.lineTo(x1,keyHeight)
      this.ctx.lineTo(x0,keyHeight)
      this.ctx.closePath();
      this.ctx.fill();

      if (this.keyColors[keyNumber] != 0) {
        switch (this.keyColors[keyNumber]){
          case (1):
            this.ctx.fillStyle = "#636e96";
            break;
          case (3):
            this.ctx.fillStyle = "#f40000";
            break;
        }

        this.ctx.beginPath();
        this.ctx.arc(x0+circleXOffset, circleYOffset, 6, 0, tau);
        this.ctx.fill();
      }

      this.ctx.save();

      if (this.bwKeys[(keyNumber-1+12)%12] == 1){
        this.drawKey(keyNumber-1)
      }
    },
    drawKeyBoard() {
      var key
      for (key=0;key<=this.lastKey;key++){
        this.drawKey(key)
      }
    },
    drawRoot() {
      this.drawKey(this.rootKey + 12)
    },
    updateScale(clean){
      if (clean == "clean") {
        this.currentChord = [];
      }
      var deg, key
      var scaleMode = this.modes[this.mode]
      rootKey = Number(this.rootKey)
      for (deg=0;deg<7;deg++){
        nDeg = (scaleMode[deg] + rootKey) % 12;
        this.scale[deg] = nDeg;
      }
      this.noteList = this.baseNoteList;
      if (this.scale.includes(6)){
        this.noteList = this.sharpList;
      }
      if (this.scale.includes(10) && (rootKey != 11)){
        this.noteList = this.flatList;
        if (this.scale.includes(3) && this.scale.includes(4)){
          this.noteList[4] = 'Fb';
        }
      }

      for (deg=0;deg<7;deg++){
        nDeg = (scaleMode[deg] + rootKey) % 12;
        this.noteScale[deg] = this.noteList[nDeg];
      }

      for (key=0;key<=this.lastKey;key++){
        if (this.currentChord.includes(key-12)){
          this.keyColors[key] = 3
        } else if (this.scale.includes(key%12)){
          this.keyColors[key] = 1
        } else {
          this.keyColors[key] = 0
        }
      }
      this.drawKeyBoard();
      vm.$forceUpdate();
    },
    playChord(root, chString){
      notes = this.chords[chString];
      c = notes.map(n => n + root);
      this.currentChord = c;
      for (n in c) {
        this.ogglist[c[n]].currentTime = 0;
        this.ogglist[c[n]].play()
      }
      this.updateScale();
    },
    getGoodNote(note) {
      return this.noteList[note]
    },
    spicelvl(root, chString){
      notes = this.chords[chString];
      c = notes.map(n => n + root);
      sl = 0;
        for (n in c) {
          if (!(this.scale.includes(c[n]%12))){
            sl = sl + 1;
          }
        }
      return sl;
    },
    spice2Color(root, chString) {
      sl = this.spicelvl(root, chString);
      if (sl == 0) {
        color = "#ef3932";
      } else {
        color = "";
      }
      return color;
    },
    playScale() {
      doSomething = async () => {
        upBreak = false;
        for (n in this.scale){
          await this.sleep(200);
          note = this.scale[n];

          if (n > 0) {
            if ((note < this.scale[n-1]) || upBreak ) {
              upBreak = true;
              note = note + 12;
            }
          }

          this.ogglist[note].play();
        }
        await this.sleep(200);
        this.ogglist[this.scale[0] + 12].play();

      }
      doSomething();
    }
  },
  mounted: function() {
    var vm = this
    vm.canvas = vm.$refs.canvas
    vm.ctx = vm.canvas.getContext("2d");
    vm.ctx.lineWidth = 0;
    this.drawKeyBoard();
    this.updateScale();
  },

}).$mount('#app')