// [VexFlow](http://vexflow.com) - Copyright (c) Mohit Muthanna 2010.
//
// ## Description
//
// `Modifier` is an abstract interface for notational elements that modify
// a `Note`. Examples of modifiers are `Accidental`, `Annotation`, `Stroke`, etc.
//
// For a `Modifier` instance to be positioned correctly, it must be part of
// a `ModifierContext`. All modifiers in the same context are rendered relative to
// one another.
//
// Typically, all modifiers to a note are part of the same `ModifierContext` instance. Also,
// in multi-voice staves, all modifiers to notes on the same `tick` are part of the same
// `ModifierContext`. This ensures that multiple voices don't trample all over each other.

import { Vex } from './vex';

// To enable logging for this class. Set `Vex.Flow.Modifier.DEBUG` to `true`.
function L() { if (Modifier.DEBUG) Vex.L('Vex.Flow.Modifier', arguments); }

export class Modifier {
  static get CATEGORY() { return 'none'; }

  // Modifiers can be positioned almost anywhere, relative to a note.
  static get Position() {
    return {
      LEFT: 1,
      RIGHT: 2,
      ABOVE: 3,
      BELOW: 4,
    };
  }

  constructor() {
    this.width = 0;
    this.context = null;

    // Modifiers are attached to a note and an index. An index is a
    // specific head in a chord.
    this.note = null;
    this.index = null;

    // The `text_line` is reserved space above or below a stave.
    this.text_line = 0;
    this.position = Modifier.Position.LEFT;
    this.modifier_context = null;
    this.x_shift = 0;
    this.y_shift = 0;
    this.spacingFromNextModifier = 0;
    L('Created new modifier');
  }

  // Every modifier has a category. The `ModifierContext` uses this to determine
  // the type and order of the modifiers.
  getCategory() { return Modifier.CATEGORY; }

  // Get and set modifier widths.
  getWidth() { return this.width; }
  setWidth(width) { this.width = width; return this; }

  // Get and set attached note (`StaveNote`, `TabNote`, etc.)
  getNote() { return this.note; }
  setNote(note) { this.note = note; return this; }

  // Get and set note index, which is a specific note in a chord.
  getIndex() { return this.index; }
  setIndex(index) { this.index = index; return this; }

  // Get and set rendering context.
  getContext() { return this.context; }
  setContext(context) { this.context = context; return this; }

  // Every modifier must be part of a `ModifierContext`.
  getModifierContext() { return this.modifier_context; }
  setModifierContext(c) { this.modifier_context = c; return this; }

  // Get and set articulation position.
  getPosition() { return this.position; }
  setPosition(position) { this.position = position; return this; }

  // Set the `text_line` for the modifier.
  setTextLine(line) { this.text_line = line; return this; }

  // Shift modifier down `y` pixels. Negative values shift up.
  setYShift(y) { this.y_shift = y; return this; }

  setSpacingFromNextModifier(x) {
    this.spacingFromNextModifier = x;
  }

  getSpacingFromNextModifier() { return this.spacingFromNextModifier; }

  // Shift modifier `x` pixels in the direction of the modifier. Negative values
  // shift reverse.
  setXShift(x) {
    this.x_shift = 0;
    if (this.position == Modifier.Position.LEFT) {
      this.x_shift -= x;
    } else {
      this.x_shift += x;
    }
  }
  getXShift() { return this.x_shift; }

  // Render the modifier onto the canvas.
  draw() {
    if (!this.context) throw new Vex.RERR('NoCanvasContext',
        "Can't draw without a canvas context.");
    throw new Vex.RERR('MethodNotImplemented',
        'Draw() not implemented for this modifier.');
  }
}

@@ -818,16 +818,23 @@
 ction L(
+...args
 ) %7B if (
@@ -883,13 +883,8 @@
  arg
-ument
 s); 
@@ -3241,16 +3241,17 @@
 ition ==
+=
  Modifie
@@ -3457,16 +3457,24 @@
 context)
+ %7B%0A     
  throw n
@@ -3503,24 +3503,16 @@
 ontext',
-%0A       
  %22Can't 
@@ -3545,16 +3545,23 @@
 ext.%22);%0A
+    %7D%0A%0A
     thro
@@ -3602,19 +3602,11 @@
 ed',
-%0A       
  '
-D
+d
 raw(

Fix remaining lint problems in modifier.js