/**
 * Parses a string of well-formed JSON text.
 *
 * If the input is not well-formed, then behavior is undefined, but it is
 * deterministic and is guaranteed not to modify any object other than its
 * return value.
 *
 * This does not use `eval` so is less likely to have obscure security bugs than
 * json2.js.
 * It is optimized for speed, so is much faster than json_parse.js.
 *
 * This library should be used whenever security is a concern (when JSON may
 * come from an untrusted source), speed is a concern, and erroring on malformed
 * JSON is *not* a concern.
 *
 *                      Pros                   Cons
 *                    +-----------------------+-----------------------+
 * json_sans_eval.js  | Fast, secure          | Not validating        |
 *                    +-----------------------+-----------------------+
 * json_parse.js      | Validating, secure    | Slow                  |
 *                    +-----------------------+-----------------------+
 * json2.js           | Fast, some validation | Potentially insecure  |
 *                    +-----------------------+-----------------------+
 *
 * json2.js is very fast, but potentially insecure since it calls `eval` to
 * parse JSON data, so an attacker might be able to supply strange JS that
 * looks like JSON, but that executes arbitrary javascript.
 * If you do have to use json2.js with untrusted data, make sure you keep
 * your version of json2.js up to date so that you get patches as they're
 * released.
 *
 * @param {string} json per RFC 4627
 * @return {Object|Array}
 * @author Mike Samuel <mikesamuel@gmail.com>
 */
var jsonParse = (function () {
  var number = '(?:-?\\b(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b)';
  var oneChar = '(?:[^\\0-\\x08\\x0a-\\x1f\"\\\\]' + '|\\\\(?:[\"/\\\\bfnrt]|u[0-9A-Fa-f]{4}))';
  var string = '(?:\"' + oneChar + '*\")';

  // Will match a value in a well-formed JSON file.
  // If the input is not well-formed, may match strangely, but not in an unsafe
  // way.
  // Since this only matches value tokens, it does not match whitespace, colons,
  // or commas.
  var jsonToken = new RegExp(      '(?:false|true|null|[\\{\\}\\[\\]]'      + '|' + number      + '|' + string      + ')', 'g');

  // Matches escape sequences in a string literal
  var escapeSequence = new RegExp('\\\\(?:([^u])|u(.{4}))', 'g');

  // Decodes escape sequences in object literals
  var escapes = {    '"': '"',    '/': '/',    '\\': '\\',    'b': '\b',    'f': '\f',    'n': '\n',    'r': '\r',    't': '\t'  };
  function unescapeOne(_, ch, hex) {
    return ch ? escapes[ch] : String.fromCharCode(parseInt(hex, 16));
  }

  // A non-falsy value that coerces to the empty string when used as a key.
  var EMPTY_STRING = new String('');
  var SLASH = '\\';

  // Constructor to use based on an open token.
  var firstTokenCtors = { '{': Object, '[': Array };

  return function (json) {
    // Split into tokens
    var toks = json.match(jsonToken);
    // Construct the object to return
    var result;
    var tok = toks[0];
    if ('{' === tok) {
      result = {};
    } else if ('[' === tok) {
      result = [];
    } else {
		alert('An error occured');
		result = [];
      //throw new Error(tok);
    }

    // If undefined, the key in an object key/value record to use for the next
    // value parsed.
    var key;
    // Loop over remaining tokens maintaining a stack of uncompleted objects and
    // arrays.
    var stack = [result];
    for (var i = 1, n = toks.length; i < n; ++i) {
      tok = toks[i];

      var cont;
      switch (tok.charCodeAt(0)) {
        case 0x22:  // '"'
          tok = tok.substring(1, tok.length - 1);
          if (tok.indexOf(SLASH) !== -1) {
            tok = tok.replace(escapeSequence, unescapeOne);
          }
          cont = stack[0];
          if (!key) {
            if (cont instanceof Array) {
              key = cont.length;
            } else {
              key = tok || EMPTY_STRING;  // Use as key for next value seen.
              break;
            }
          }
          cont[key] = tok;
          key = 0;
          break;
        case 0x5b:  // '['
          cont = stack[0];
          stack.unshift(cont[key || cont.length] = []);
          key = 0;
          break;
        case 0x5d:  // ']'
          stack.shift();
          break;
        case 0x66:  // 'f'
          cont = stack[0];
          cont[key || cont.length] = false;
          key = 0;
          break;
        case 0x6e:  // 'n'
          cont = stack[0];
          cont[key || cont.length] = null;
          key = 0;
          break;
        case 0x74:  // 't'
          cont = stack[0];
          cont[key || cont.length] = true;
          key = 0;
          break;
        case 0x7b:  // '{'
          cont = stack[0];
          stack.unshift(cont[key || cont.length] = {});
          key = 0;
          break;
        case 0x7d:  // '}'
          stack.shift();
          break;
        default:  // sign or digit
          cont = stack[0];
          cont[key || cont.length] = +(tok);
          key = 0;
          break;
      }
    }
    // Fail if we've got an uncompleted object.
    if (stack.length) { throw new Error(); }
    return result;
  };
})();


function resetForm() {
	$('#title').html('');
	
	$('#spinner').css('display', 'none');
	$('#btn').css('display', 'inline');
	$('#btn-container').attr('disabled', '');
	$('#statusGainContainer').css('display', 'none');
	$('#result').val('');
	$('#statusLine').val('');
	$('#statusLine').css('visibility', 'hidden');
}

function makeRequest() { 

	if($('#pasted').val() == "still in beta!" || $('#pasted').val() === "" ) {
		alert('Please enter JavaScript code.');
		return;
	}

	if($('#pasted').val().length > 65000 ) {
		alert('Please enter no more than 65000 bytes. This is a tiny machine, have mercy :)');
		return;
	}

	$('#btn-container').attr('disabled', 'disabled');
	$('#btn').css('display', 'none');
	$('#spinner').css('display', 'inline');
	$('#statusGainContainer').css('display', 'none');
	$('#statusLine').css('visibility', 'hidden');
	$('#result').val('');
	
	
	var data = {pasted: $('#pasted').val(), processwhat: $('select[name="processwhat"]').val()};
	
	$.ajax(
	{
		type: "POST",
		url: '/tools/index.php/minify/process',
		data: data,
		dataType: "json",
		timeout: (10 * 1000),	 
		 
		success: function(json){
			$('#spinner').css('display', 'none');
			$('#btn').css('display', 'inline');
			$('#btn-container').attr('disabled', '');
			$('#statusGainContainer').css('display', 'block');
	
			var result = $('#result');
			result.val(json.result.processed);
			result.focus();
					
			
			$('#statusLine').css('visibility', 'visible');
			$('#statusLine').html('<span class="success">'+json.result.status+'</span>');
			$('#statusGain').html(json.result.gain);
			$('#result').select();
		},
		error: function( objAJAXRequest, strError ){
		
			resetForm();	
			
            var t = jsonParse(objAJAXRequest.responseText);

			$('#statusLine').css('visibility', 'visible');
			
			if(t && t.result && t.result.errmsg) {
				$('#statusLine').html('<span class="error">'+t.result.errmsg+'</span>');
			} else {
				$('#statusLine').html('<span class="error">An error has occurred</span>');
			}


		}
	});
}

$(document).ready(function() { 
	if($('#btn-container')) {
		$('#btn-container').click(makeRequest);
	}
	resetForm();

	$('#pasted').val('still in beta!');
	$('#pasted').click(function(){$('#pasted').val('');});

	
});