
var Note = require('./note')

module.exports = Notes

var CHANNEL_MAPPING = {
  IIDX_P1: {
    '11': { column: '1'  },
    '12': { column: '2'  },
    '13': { column: '3'  },
    '14': { column: '4'  },
    '15': { column: '5'  },
    '18': { column: '6'  },
    '19': { column: '7'  },
    '16': { column: 'SC' },
  },
}

/**
 * The Notes class holds the Note objects in the game. A note object may or
 * may not be playable.
 *
 * @class Notes
 * @constructor
 */
function Notes(notes) {
  notes.forEach(Note.validate)
  this._notes = notes
}

/**
 * Returns the number of notes in this object.
 *
 * @method count
 * @return {Number}
 */
Notes.prototype.count = function() {
  return this._notes.length
}

/**
 * Returns an Array of all notes.
 *
 * @method all
 * @return {Note[]}
 */
Notes.prototype.all = function() {
  return this._notes.slice()
}

/**
 * Creates a Notes object from a BMSChart.
 *
 * @static
 * @method fromBMSChart
 * @param {BMSChart} chart    the chart to process
 * @param {Object}   options  the note options
 */
Notes.fromBMSChart = function(chart, options) {
  options = options || { }
  var builder = new BMSNoteBuilder(chart)
  return builder.build()
}

function BMSNoteBuilder(chart) {
  this._chart = chart
}

BMSNoteBuilder.prototype.build = function() {
  this._notes = []
  this._activeLN = { }
  this._channelMapping = CHANNEL_MAPPING.IIDX_P1
  this._objects = this._chart.objects.allSorted()
  this._objects.forEach(function(object) {
    this._handle(object)
  }.bind(this))
  return new Notes(this._notes)
}

BMSNoteBuilder.prototype._handle = function(object) {
  if (object.channel === '01') {
    this._handleNormalNote(object)
  } else {
    switch (object.channel.charAt(0)) {
    case '1': case '2':
      this._handleNormalNote(object)
      break
    case '5': case '6':
      this._handleLongNote(object)
      break
    }
  }
}

BMSNoteBuilder.prototype._handleNormalNote = function(object) {
  var channel = this._normalizeChannel(object.channel)
  var beat = this._getBeat(object)
  this._notes.push({
    beat: beat,
    endBeat: undefined,
    keysound: object.value,
    column: this._getColumn(channel),
  })
}

BMSNoteBuilder.prototype._handleLongNote = function(object) {
  var channel = this._normalizeChannel(object.channel)
  var beat = this._getBeat(object)
  if (this._activeLN[channel]) {
    var note = this._activeLN[channel]
    note.endBeat = beat
    this._notes.push(note)
    ;delete this._activeLN[channel]
  } else {
    this._activeLN[channel] = {
      beat: beat,
      keysound: object.value,
      column: this._getColumn(channel),
    }
  }
}

BMSNoteBuilder.prototype._getBeat = function(object) {
  return this._chart.measureToBeat(object.measure, object.fraction)
}

BMSNoteBuilder.prototype._getColumn = function(channel) {
  return this._channelMapping[channel]
}

BMSNoteBuilder.prototype._normalizeChannel = function(channel) {
  return channel.replace(/^5/, '1').replace(/^6/, '2')
}


@@ -1328,16 +1328,110 @@
 N = %7B %7D%0A
+  this._lastNote = %7B %7D%0A  this._lnObj = (this._chart.headers.get('lnobj') %7C%7C '').toLowerCase()%0A
   this._
@@ -2130,27 +2130,174 @@
 )%0A  
-this._notes.push(%7B%0A
+if (object.value.toLowerCase() === this._lnObj) %7B%0A    if (this._lastNote%5Bchannel%5D) %7B%0A      this._lastNote%5Bchannel%5D.endBeat = beat%0A    %7D%0A  %7D else %7B%0A    var note = %7B%0A  
     
@@ -2304,24 +2304,26 @@
 beat: beat,%0A
+  
     endBeat:
@@ -2334,24 +2334,26 @@
 efined,%0A    
+ 
+ 
 keysound: ob
@@ -2360,24 +2360,26 @@
 ject.value,%0A
+  
     column: 
@@ -2410,10 +2410,77 @@
 ,%0A  
+  %7D%0A    this._lastNote%5Bchannel%5D = note%0A    this._notes.push(note)%0A  
 %7D
-)
 %0A%7D%0A%0A

add LNOBJ support