var Scale = {

  // scale or code
  mode: null,

  selectedName: null,

  selectedScale: null,

  selectedScale_r: null,

  rootNote: null,

  notes: {
    "A":  0,
    "B♭": 1,
    "B":  2,
    "C":  3,
    "C#": 4,
    "D":  5,
    "E♭": 6,
    "E":  7,
    "F":  8,
    "F#": 9,
    "G":  10,
    "G#": 11
  },

  // This maked Scale.createRelativiteNotes.
  notes_r: [],

  // 1st -> 7th
  stringRoot: null,

  strings: {
    "6" : 6,
    "7" : 7
  },

  // 6 or 7
  stringCount: null,

  scaleName: null,

  codeName: null,

  codes: {
    "M"      : "0,4,7",
    "m"      : "0,3,7",
    "m(♭5)"  : "0,3,6",
    "aug"    : "0,4,8",
    "7"      : "0,4,7,10",
    "M7"     : "0,4,7,11",
    "m7"     : "0,3,7,10",
    "m7♭5"   : "0,3,6,10",
    "dim7"   : "0,3,6,9",
    "augM7"  : "0,4,8,11",
    "mM7"    : "0,3,7,11",
    "7(9)"   : "0,4,7,10,14",
    "7(♭9)"  : "0,4,7,10,13",
    "sus4"   : "0,5,7",
    "7sus4"  : "0,5,7,10",
    "6"      : "0,4,7,9",
    "m6"     : "0,3,7,9",
    "7#11"   : "0,4,7,10,18",
    "7(13)"  : "0,4,7,10,21",
    "7(♭13)" : "0,4,7,10,20",
    "add2"   : "0,2,4,7",
    "add4"   : "0,4,5,7",
    "-5"     : "0,4,6",
    "7-5"    : "0,4,6,10",
    "Power"  : "0,7"
  },

  scales: {
    "Major"           : "0,2,4,5,7,9,11",
    "Major Pentatonic": "0,2,4,7,9",
    "Minor Pentatonic": "0,3,5,7,10",
    "Natural Minor"   : "0,2,3,5,7,8,10",
    "Harmonic Minor"  : "0,2,3,5,7,8,11",
    "Melodic Minor"   : "0,2,3,5,7,9,11",
    "Blue Note"       : "0,2,3,5,6,7,9,10",
    "Ionian"          : "0,2,4,5,7,9,11",
    "Dorian"          : "0,2,3,5,7,9,10",
    "Phrygian"        : "0,1,3,5,7,8,10",
    "Lydian"          : "0,2,4,6,7,9,11",
    "Mixolydian"      : "0,2,4,5,7,9,10",
    "Aeolian"         : "0,2,3,5,7,8,10",
    "Locrian"         : "0,1,3,5,6,8,10",
    "Diminish"        : "0,2,3,5,6,8,9,11",
    "WholeTone"       : "0,2,4,6,8,10",
    "Chromatic"       : "0,1,2,3,4,5,6,7,8,9,10,11",
    "Spanish"         : "0,1,3,4,5,7,8,10",
    "Hungarian"       : "0,2,3,6,7,8,11",
    "Japanese Minyo"  : "0,3,5,7,10",
    "Ryukyu"          : "0,4,5,7,11"
  },

  // For style sheet
  scaleWidth: [
   "18","56","53","50","47","45","42","39","37","35","33","29","28","26","25",
   "24","23","21","19","18","17","16","15","14","14","13","13","12","1"
  ],

  createRelativiteNotes: function() {
    for (k in this.notes) this.notes_r[this.notes[k]] = k;
  },

  downNote: function(note) {
    return this.notes_r[(this.notes[note] == 0) ? 11 : this.notes[note] - 1];
  },

  upNote: function(note) {
    return this.notes_r[(this.notes[note] == 11) ? 0 : this.notes[note] + 1];
  },

  getNote: function(range) {
    if (range > 23) {
      range -= 24;
    } else if (range > 11) {
      range -= 12;
    } else if (range < 0) {
      range += 12;
    }
    return this.notes_r[range];
  },

  scaleMatch: function(note) {
    return (this.selectedScale_r[note] != null) ? true : false;
  },

  setting: function(mode, stringCount, stringRoot, scaleName, codeName, rootNote) {
    this.mode = mode;
    this.stringCount = stringCount;
    this.stringRoot = stringRoot;
    this.scaleName = scaleName;
    this.codeName = codeName;
    this.rootNote = rootNote;
    if (Macro.enabled) {
      Macro.add(rootNote, codeName);
    }
    if (mode == "scale") { 
      this.selectedName = scaleName;
    } else if (mode == "code") {
      this.selectedName = codeName;
    }
    var createdScale = this.createScale(mode, this.selectedName, rootNote);
    this.selectedScale = createdScale["scale"];
    this.selectedScale_r = createdScale["scale_r"];
  },

  createScale: function(mode, name, rootNote) {
    var scale = [];
    var scale_r = {};
    var range = this.notes[rootNote];
    var nowScale;
    if (mode == "scale") {
      nowScale = this.scales[name].split(",");
    } else if (mode == "code") {
      nowScale = this.codes[name].split(",");
    }
    for (var i = 0, n = nowScale.length; i < n; i++) {
      var targetRange = parseInt(nowScale[i]) + range;
      var targetNote = this.getNote(targetRange);
      scale[i] = targetNote;
      scale_r[targetNote] = targetRange;
    }
    return {"scale":scale, "scale_r":scale_r};
  }

}