var mouseState = false;
var mouseX = 0;
var fretWidth = 50;
var stringHeight = 0;
var nStrings = 6;
var lastFretLeft = -100;
var lastStep = -100;
var leftOffset = 0;
var nFrets = 4;
var scaleNotes;
var maxFret = 21;
var onNotes = new Array();
var doAlert = true;
var selectorMin = 0;
var selectorMax = 0;
var hiColor = '#66FF00';
var openHiColor = 'green';
var keySigWidth = 30;
var tabLineHeight = 20;
var direction = 1;

// Find toFind in ar.
function arrayIndexOf(ar, toFind)
{
  len = ar.length;
  for (i = 0; i < len; i++) {
    if (ar[i] == toFind) return i;
  }
  return -1;
}

// ES: It would be better to just define some globals right on the page itself.
function initPage(fretWidthIn, stringHeightIn, nStringsIn, scaleNotesIn, tabLineHeightIn,
		  selectorLeftIn, directionIn)
{
  direction = directionIn;
  fretWidth = Number(fretWidthIn);
  stringHeight = Number(stringHeightIn);
  nStrings = Number(nStringsIn);
  fretboardEl = document.getElementById("id_fretboard");
  leftOffset = fretWidthIn;
  scaleNotes = scaleNotesIn;
  tabLineHeight = tabLineHeightIn;
  selectorMin = fretWidth;
  selectorEl = document.getElementById("selector");
  selectorMax = fretWidth * 19;
  if (selectorLeftIn >= selectorMin && selectorLeftIn <= selectorMax) {
      selectorEl.style.left = selectorLeftIn + 'px';
      doSelect(selectorLeftIn);
  } else {
    doSelect(selectorMin);
  }
  doDrop();
}



function mouseDown(newX)
{
  //  selectorEl = document.getElementById("selector");
  //  l = selectorEl.style.left;
  //  alert(Number(l.substring(0, l.length-2)));
  mouseState = true;
  mouseX = newX;
}

// Starting at fretIndex, moves in the direction of step to find the
// first note on the given string. Returns the new fretIndex, or -1 if
// not found.
function findNote(fretIndex, stringIndex, step)
{
  for (i = fretIndex; i >= 0 && i <= maxFret; i += step) {
    // Try to get the image element.
    elName = 'id_label_'+stringIndex+'_'+i;
    el = document.getElementById(elName);
    if (el) {
      return i;
    }
  }
  return -1;
}

function mouseMove(newX)
{
  if (mouseState) {
    change = newX - mouseX;
    selectorEl = document.getElementById("selector");
    //selection.clearSelection();
    oldLeft = selectorEl.offsetLeft;
    newLeft = oldLeft + change;
    if (newLeft < selectorMin) {
      newLeft = selectorMin;
    }
    if (newLeft > selectorMax) newLeft = selectorMax;

    doSelect(newLeft);
    doDrop();

    selectorEl.style.left = newLeft + 'px';
     
    selLeftEl = document.getElementById('id_selLeft');
    selLeftEl.value = newLeft;
    mouseX = newX;
  }
}

function highlightNote(imgEl, labelEl, notesToClear)
{
  index = arrayIndexOf(notesToClear, imgEl);
  if (index == -1) {
    strArr = imgEl.id.split('_');
    if (strArr[3] == '0') {
      labelEl.style.color = openHiColor;
    } else {
      labelEl.style.color = hiColor;
    }
    imgEl.src = imgEl.src.replace('.gif', '-hi.gif');
  } else {
    notesToClear[index] = null;
  }
  onNotes.push(imgEl);
}

function doSelect(newLeft)
{
  // Find the left-most fret at least half-covered by the box.
  fretLeft = Math.round((newLeft - leftOffset) / fretWidth);
  if (fretLeft < 0) fretLeft = 0;
  fretRight = fretLeft + nFrets;
  // When we need a note that's outside the box, go left or right?
  if (fretRight >= maxFret || (fretLeft > 0 && fretLeft > (newLeft - leftOffset) / fretWidth)) {
    step = -1;
  } else {
    step = 1;
  }

  if (fretLeft != lastFretLeft || step != lastStep) { // If selection has changed.
    //onsole.log('****** step is ', step);
    tabAreaEl = document.getElementById('id_tabList');
    //tabAreaEl.innerHTML = '';
    notesToClear = onNotes;
    onNotes = [];
    scaleIndex = -1;
    numNotes = scaleNotes.length;
    for (stringIndex = 0; stringIndex < nStrings; stringIndex++) {
      for (fretIndex = fretLeft; fretIndex < fretRight; fretIndex++) {
	// Try to get the image element.
	elName = 'id_img_'+stringIndex+'_'+fretIndex;
	var imgEl = document.getElementById(elName);
	if (imgEl) {
	  // Found a note.
	  elName = 'id_label_'+stringIndex+'_'+fretIndex;
	  labelEl = document.getElementById(elName);
	  noteName = labelEl.innerHTML;
	  if (scaleIndex == -1) {
	    // First note.
	    scaleIndex = arrayIndexOf(scaleNotes, noteName);
	  } else {
	    // Is it the note we want?
	    if (scaleNotes[scaleIndex] != noteName) {
	      // No. How far off are we?
	      newScaleIndex = arrayIndexOf(scaleNotes, noteName);
	      diff = (newScaleIndex + numNotes - scaleIndex) % numNotes;
	      //onsole.log('wanted ', scaleNotes[scaleIndex],', got ', noteName, ' diff ', diff);
	      if (diff > numNotes / 2) {
		// Best just to skip this note. Go to next fret.
		//onsole.log('skipping.');
		continue;
	      }
	    }
	    workingStep = step;
	    while (scaleNotes[scaleIndex] != noteName) {
	      // Now try to find the note we want.
	      if (workingStep == 1 && stringIndex != 0) { // Previous string, to the right.
		fillInStringIndex = stringIndex - 1;
		fillInFretIndex = findNote(fretRight, fillInStringIndex, workingStep);
	      } else { // Current string, to the left.
		fillInStringIndex = stringIndex;
		fillInFretIndex = findNote(fretLeft - 1, fillInStringIndex, workingStep);
	      }
	      elName = 'id_label_'+fillInStringIndex+'_'+fillInFretIndex;
	      fillInLabelEl = document.getElementById(elName);
	      //onsole.log('fillInLabelEl ', fillInLabelEl);
	      //onsole.log('innerHTML ', fillInLabelEl.innerHTML, ' wanted ', scaleNotes[scaleIndex]);
	      if (fillInLabelEl && fillInLabelEl.innerHTML == scaleNotes[scaleIndex]) {
		//onsole.log('found it');
		elName = 'id_img_'+fillInStringIndex+'_'+fillInFretIndex;
		fillInImgEl = document.getElementById(elName);
		// Turn on fill-in highlight.
		highlightNote(fillInImgEl, fillInLabelEl, notesToClear);
		workingStep = step;
	      } else if (workingStep == step) {
		// Couldn't find it! Try the other direction.
		workingStep = -workingStep;
		//onsole.log('Couldnt find it: new workingStep', workingStep);
		continue;
	      }
	      scaleIndex = (scaleIndex + 1) % scaleNotes.length;
	    }
	  }
	  highlightNote(imgEl, labelEl, notesToClear);
	  scaleIndex = (scaleIndex + 1) % scaleNotes.length;
	}
      }
    }

    for (i = 0; i < notesToClear.length; i++) {
      imgEl = notesToClear[i];
      if (imgEl) {
	elName = 'id_label' + imgEl.id.substring(6, 100);
	labelEl = document.getElementById(elName);
	labelEl.style.color = '';
	imgEl.src = imgEl.src.replace('-hi', '');
      }
    }
    lastFretLeft = fretLeft;
    lastStep = step;
  }
}

function mouseUp(newX)
{
  if (mouseState) {
    mouseState = false;
    doDrop();
  }
}

var staffStep = 10; // Distance between lines, in pixels.
var staffTotalPadding = 80; // Top and bottom padding.
var staffMessageTop = 25;

function doDrop()
{
  tabText = '';
  staffText = '';
  nNotes = onNotes.length;
  tabTableEl = document.getElementById('id_tabTable');
  staffTableEl = document.getElementById('id_staffTavle');
  noteStep = Math.round((tabTableEl.clientWidth - keySigWidth) / (nNotes));
  theLeft = Math.round(noteStep / 2 + keySigWidth); // ES: Replace magic #s.
  if (direction == -1) {
    theLeft += (nNotes-1) * noteStep;
  }
  noteOffset = 0;
  for (i = 0; i < nNotes; i++) {
    imgEl = onNotes[i];
    strArr = imgEl.id.split('_');
    stringIndex = strArr[2];
    fretIndex = strArr[3];
    // ** Fill in the tab number.
    tabTop = (nStrings - stringIndex - 1.5) * tabLineHeight; // ES: Replace magic #s.
    if (imgEl.src.indexOf('root') != -1) {
      styleAddition = '; font-weight:bold; color:red';
    } else {
      styleAddition = '';
    }
    tabText += '<div class="tabNumber" style="left:'+theLeft+'; top:'+tabTop+styleAddition+'">'+fretIndex+'</div>\n';
    // ** Fill in the note.
    labelEl = document.getElementById('id_label_'+stringIndex+'_'+fretIndex);
    if (i == 0) {
      // Since F is the top line, adjust.
      noteNum = 21 - noteNameToNum(labelEl.innerHTML);
      while (noteNum + noteOffset > 17) {
	noteOffset -= 7;
      }
      noteNum += noteOffset;
      tdEl = document.getElementById('id_tab_td');
      pb = staffStep * 4 - (14 - noteNum) * staffStep / 2;// ES: Replace magic #s.
      tdEl.style.paddingBottom = pb;
      tdEl.style.paddingTop = staffTotalPadding - pb;
      document.getElementById('id_staffMessage').style.top = staffMessageTop + pb;
      lastNote = noteNum;
    } else {
      noteNum = 21 - noteNameToNum(labelEl.innerHTML) + noteOffset;
      if (noteNum > lastNote) {
	noteNum -=7;
	noteOffset -=7;
      }
      lastNote = noteNum;
    }
    // ** Add ledger lines, if necessary.
    if (noteNum >= 12) {
      for (ledgerNum = 11; ledgerNum < noteNum; ledgerNum += 2) {
	ledgerTop = ledgerNum * staffStep / 2 - 5;  // ES: Replace magic #s.
	staffText += '<div class="ledgerLine" style="left:'+(theLeft-5)+ '; top:'+ledgerTop+'"></div>\n';
      }
    } else if (noteNum < 1) {
      for (ledgerNum = 0; ledgerNum > noteNum-2; ledgerNum -= 2) {
	ledgerTop = ledgerNum * staffStep / 2 - 5;  // ES: Replace magic #s.
	staffText += '<div class="ledgerLine" style="left:'+(theLeft-5)+ '; top:'+ledgerTop+'"></div>\n';
      }
    }      
    noteTop = noteNum * staffStep / 2 - 15;  // ES: Replace magic #s.
    if (noteNum > 4) {
      noteSrc = '/images/quarternoteup.gif';
      noteTop -= 22;
    } else {
      noteSrc = '/images/quarternotedown.gif';
    }
    staffText += '<img style="position:absolute; left:'+theLeft+'; top:'+noteTop+'" src="'+noteSrc+'"/>\n';
    theLeft += noteStep * direction;
  }
  tabAreaEl = document.getElementById('id_tabList');
  tabAreaEl.innerHTML = tabText;
  staffAreaEl = document.getElementById('id_staffList');
  staffAreaEl.innerHTML = staffText;
}

var noteList = ["A", "B", "C","D", "E", "F", "G"];
function noteNameToNum(note)
{
  // IE doesn't support indexOf member.
  note = note.substring(0,1);
  len = noteList.length;
  for (var i = 0; i < len; i++) {
    if (noteList[i] == note) {
      return i;
    }
  }
  return -1;
}

function selectTabMenu(tabEl)
{
  allTabEls = document.getElementById('id_tabMenuArea').getElementsByTagName('a');
  for (i = 0; i < allTabEls.length; i++) {
    if (allTabEls[i].className == 'activeTab' && allTabEls[i] != tabEl) {
      allTabEls[i].className = 'menuTab';
    }
  }
  tabEl.className = 'activeTab';
  bodyId = tabEl.id.replace('_tab', '');
  bodyEl = document.getElementById(bodyId);
  allBodyEls = document.getElementById('id_tabMenuArea').getElementsByTagName('div');
  for (i = 0; i < allBodyEls.length; i++) {
    if (allBodyEls[i].className == 'tabMenuBody' && allBodyEls[i] != bodyEl) {
      allBodyEls[i].style.display = 'none';
    }
  }
  bodyEl.style.display = 'block';
  menuTabEl = document.getElementById('id_menuTab');
  menuTabEl.value = bodyId.replace('id_', '');
  return false;
}


function showMoreOptions()
{
  var showOptionsEl = document.getElementById('showOptions');
  var optionsEl = document.getElementById('moreOptions');
  var optionsDispEl = document.getElementById('id_optionsDisp');

  showOptionsEl.style.display = 'none';
  optionsEl.style.display = 'inline';
  optionsDispEl.value = 'inline';

  return false;
}

function showFewerOptions()
{
  var showOptionsEl = document.getElementById('showOptions');
  var optionsEl = document.getElementById('moreOptions');
  var optionsDispEl = document.getElementById('id_optionsDisp');

  showOptionsEl.style.display = 'inline';
  optionsEl.style.display = 'none';
  optionsDispEl.value = 'none';

  return false;
}

function submitting()
{
  var optionsDispEl = document.getElementById('id_optionsDisp');

  if (optionsDispEl.value == 'none') {
    // Options are not show. Use defaults.
    var tuningEl = document.getElementById('id_tuning');
    var tuningNameEl = document.getElementById("id_tuningName");

    tuningEl.value = 'EADGBE';
    tuningNameEl.selectedIndex = 0;
  }
  return true;
}

function newScale(anchor)
{
  selectorEl = document.getElementById("selector");
  optionsDispEl = document.getElementById('id_optionsDisp');
  anchor.href += encodeURI('&selLeft=' + selectorEl.offsetLeft +
			   '&optionsDisp=' + optionsDispEl.value);
  return true;
}

function tuningNameChanged()
{
  var tuningEl = document.getElementById("id_tuning");
  var tuningNameEl = document.getElementById("id_tuningName");

  if (tuningNameEl.value != '<Custom>') {
    tuningEl.value = tuningNameEl.value;
    selectedTuning = tuningNameEl.value;
  } else {
    tuningEl.focus();
    tuningEl.select();
  }
}

function tuningChanged()
{
  var tuningEl = document.getElementById("id_tuning");
  var tuningNameEl = document.getElementById("id_tuningName");

  tuningValue = '';
  for(i = 0; i < tuningEl.value.length; i++) {
    if (tuningEl.value.charAt(i) != 'b') {
      tuningValue += tuningEl.value.charAt(i).toUpperCase();
    } else {
      tuningValue += tuningEl.value.charAt(i);
    }
  }
  if (tuningValue != selectedTuning) {
    if (tuningNameEl.value != tuningValue) {
      for (i = 0; i < tuningNameEl.length; i++) {
	if (tuningNameEl[i].value == tuningValue) {
	  tuningNameEl.selectedIndex = i;
	  return;
	}
      }
      tuningNameEl.selectedIndex = tuningNameEl.length - 1; // custom
    }
    selectedTuning = tuningEl.value;
  }
}
