/*global $, jQuery, document, window, localStorage */
var langs = {
  'en': {
    'title': 'Now you have two problems.',
    'subtitle': 'JavaScript-powered regular expression tester',
    'pattern': 'Pattern',
    'testText': 'Test text',
    'matches': 'Matches',
    'invalidPattern': '(invalid pattern)',
    'noTest': '(no text to test)',
    'noMatch': '(no matches)',
    'addTester': 'Add tester',
    'example': 'Add example',
    'removeTester': 'Remove',
    'legal': 'Created by Garrett Albright. This entire web site is distributed under the two-clause BSD license.'
  }
},
  currLang = langs.en,
  testerCount = -1,
  localStorageWorks = false;

function parseRegex(id) {
  // Get the entered pattern
  var pattern = $('#pattern-div-' + id + ' input').val(),
    haystack = $('#haystack-' + id).val(),
    // The first character will tell us where the pattern will end.
    patternBorder = pattern.charAt(0),
    // Build a regular expression to try to extract the parts of the pattern.
    patternPattern = new RegExp('\\' +patternBorder + '(.+)\\' + patternBorder + '(.*)'),
    // Run that regular expression against the inputtedpattern to get its parts
    patternMatches = pattern.match(patternPattern),
    matches = null;
  try {
    var regex = new RegExp(patternMatches[1], patternMatches[2]);
    matches = haystack.match(regex);
  }
  catch (e) {
    $('#matches-' + id).text(currLang.invalidPattern);
    return;
  }
  if (matches === null) {
    $('#matches-' + id).text(currLang.noMatch);
  }
  else {
    var matchCount = 0,
      matchesText = '';
    //Append each match to the list of matches
    jQuery.each(matches, function(idx, match) {
      if (matchCount < 10) {
        matchesText += ' ';
      }
      var matchSpan = $('<span>').append($('<span>').addClass(matchCount % 2 ? 'match-odd' : 'match-even').text(match));  
      matchesText += matchCount + ': ' + matchSpan.html() + "\n";
      matchCount++;
    });
    $('#matches-' + id).empty().append($('<pre>').html(matchesText));
  }
}

function restripe() {
  var zebra = -1;
  $('.tester').each(function() {
    $(this).removeClass('tester-even').removeClass('tester-odd').addClass('tester-' + (zebra++ % 2 ? 'even' : 'odd'));
  });
}


function addTester() {
  testerCount++;
  $('#testers').append(
    $('<div>').attr('id', 'tester-' + testerCount).addClass('tester').append(
      $('<form>').attr('enctype', 'multipart/form-data').append(
        $('<div>').attr('id', 'pattern-div-' + testerCount).addClass('pattern-div').append(
          $('<a>').attr({'id': 'close-' + testerCount, 'href': '#'}).addClass('close').text(currLang.removeTester).click(function() {
            $('#tester-' + $(this).attr('id').match(/\d+/)).slideUp('slow', function() {
              $(this).remove();
              restripe();
            });
            return(false);
          })
        ).append(
          $('<label>').attr('for', 'pattern-' + testerCount).addClass('pattern-label').text(currLang.pattern)
        ).append(
          $('<input>').attr({'type': 'text', 'name': 'pattern-' + testerCount, 'id': 'pattern-' + testerCount}).addClass('pattern').keyup(function() {
            parseRegex($(this).attr('id').match(/\d+/));
          }).blur(function() {
            parseRegex($(this).attr('id').match(/\d+/));
          })
        )
      ).append(
        $('<div>').attr('id', 'haystack-div-' + testerCount).addClass('haystack-div').append(
          $('<label>').attr('for', 'haystack-' + testerCount).addClass('haystack-label').text(currLang.testText)
        ).append(
          $('<textarea>').attr({'name': 'haystack-' + testerCount, 'id': 'haystack-' + testerCount}).addClass('haystack').keyup(function() {
            parseRegex($(this).attr('id').match(/\d+/));
          }).blur(function() {
            parseRegex($(this).attr('id').match(/\d+/));
          })
        )
      ).append(
        $('<div>').attr('id', 'matches-div-' + testerCount).addClass('matches-div').append(
          $('<label>').addClass('matches-label').text(currLang.matches)
        ).append(
          $('<div>').attr('id', 'matches-' + testerCount)
        )
      )
    ).css('display', 'none')
  );
  // Zebra stripe
  restripe();
  $('#tester-' + testerCount).slideDown('slow');
  return testerCount;
}

function addExample() {
  // This sucks. We should be doing this a better way.
  var id = addTester();
  $('#pattern-' + id).val('/\\b\\w*[aeiou]\\w*[aeiou]\\w*\\b/g');
  $('#haystack-' + id).val('This pattern finds all words in this sentence which contain at least two vowels.');
  parseRegex(id);
}

$(document).ready(function() {
  // Test if local storage works
  // http://diveintohtml5.org/everything.html#storage
  try {
    if ('localStorage' in window && window['localStorage'] !== null) {
      localStorageWorks = true;
    }
  }
  catch(e) {
  }
  $('#testers').empty();
  if (localStorageWorks && localStorage.length) {
    // Add testers based on localStorage contents.
    // jQuery.each() doesn't properly iterate over localStorage, so…
    for (var idx = 0; idx < localStorage.length; idx++) {
      // This sucks. See addExample().
      var id = addTester(),
        split = localStorage['tester-' + idx].split("\n");
      $('#pattern-' + id).val(split.shift());
      $('#haystack-' + id).val(split.join("\n"));
      parseRegex(id);
    }
  }
  else {
    // Add a blank tester
    addTester();
  }
  // Add the buttons
  $('#wrapper').append(
    $('<div>').attr('id', 'buttons-div').append(
      $('<input>').attr({'type': 'button', 'name': 'add-tester', 'id': 'add-tester', 'value': currLang.addTester}).click(function() {
        addTester();
      })
    ).append(
      $('<input>').attr({'type': 'button', 'name': 'add-example', 'id': 'add-example', 'value': currLang.example}).click(function() {
        addExample();
      })
    )
  );
  // Hide the "About" info
  $('#about').hide();
  $('#about-link').click(function() {
    $('#about').toggle();
  });
});

/**
 * Save on window close
 */
window.onunload = function() {
  if (localStorageWorks) {
    localStorage.clear();
    var idx = 0;
    $('.tester').each(function(index, $tester) {
      var thisPattern = $('.pattern', $tester).val();
      if (thisPattern !== '') {
        localStorage['tester-' + (idx++)] = thisPattern + "\n" + $('.haystack', $tester).val();
      }
    });
  }
};

