$(function(){
    var inp = $('#char_input');
    $('span.help_example').click(
      function(event){
	inp.val($(event.target).html().replace('&amp;','&'));
	inp.keyup();
      }
    );
    $('#char_erase').click(
      function(event){
	inp.val('');
	$('#input_glyph').html('');
	$('#browser_glyph').html('');
	$('#char_output').html('');
	inp.focus();
      }
    );
    inp.keydown(
      function(event){
	if (event.which>32){
	  var ch = $.trim($(event.target).val()).charAt(0);
	  if ($.inArray(ch,['#','?','&','!'])==-1){
	    inp.val('');
	  }
	}
      });
    inp.keyup(process_input);
    window['_charcodes']=[];
    upload_charcodes(0);
    var img = new Image();
    img.src = 'sprites/0.png';
    fill_val_from_hash();
    if ($.trim(inp.val()) != ''){
      inp.keyup();
    }

    $.getJSON("json/keywords.json",
	     function(json){
	       window['keywords'] = json;
	     });
  });


function fill_val_from_hash(){
  var chr = String.fromCharCode(parseInt(location.hash.slice(1)));
  if (chr.charCodeAt(0)==0) {
    $('#char_input').val('');
    } else {
      $('#char_input').val(chr);
      }
}

function upload_charcodes(i,code){
  $.getJSON('json/'+i+".json",
	    function(json){
	      for (var itm in json){
		_charcodes[itm]=json[itm];
	      };
	      if (code){
		display_charcode(code);
	      }
	    });
}

function process_input(event) {
  var val = $.trim($(event.target).val());

  if (val == ''){
    $('#char_erase').click();
    return;
      }
  var fff;

  if (val.length > 1) {
    switch (val.charAt(0)) {
      case '?':
	resolve_keyword(val.slice(1));
	return;
      case '!':
	resolve_script(val.slice(1));
	return;
      case '&':
      resolve_entity(val.slice(1));
	return;
      case '#':
      if (val.charAt(1)=='x'){
	if (val.length==2){return;}
	else if (val.slice(2).match(/[^0-9a-fA-F]/)){
	  fff=NaN;
	} else {
	  fff=parseInt(val.slice(2),16);
	}
      } else {
      	fff = parseInt(val.slice(1));
      }
	break;
      default:
	fff = val.charCodeAt(val.length-1);
    }
  } else {
    fff = val.charCodeAt(0);
  }

  display_charcode(fff);
}

function display_charcode(code){
  if (isNaN(code)){
    $('#input_error').html("Wrong input");
    return;
  }
  if (code>Math.pow(2,16)){
    $('#input_error').html("Character outside base plane");
    return;
  }
  $('#input_error').html("&nbsp;");
  var spriteStep = 128;
  var filebase = Math.floor(code/spriteStep);
  if (!_charcodes[code]) {
    upload_charcodes(filebase,code);
    return;
  }
  var dct = _charcodes[code];
  $('#input_glyph').html(image_div(code));
  $('#browser_glyph').html("<span style='font-size:400%; color:#1C6159;'>&#"+code+";</span>");
  var tmp = [];
  tmp.push("<table>");
  var th="<tr><th style='width:6em;text-align:right; padding-right:1em'>";
  tmp.push(th+int2unicodeString(code)+':</th><td>'+dct.name+ "<br> ("+categories[dct.cat]+")</td></tr>");
  tmp.push(th+'Script:</th><td>'+script_link(dct.script)+"</td></tr>");
  tmp.push(th+"Chart:</th><td>"+chart_link(dct.script)+"</td></tr>");
  tmp.push("</table>");
  tmp.push("<table style='margin-top:1em'>");
  tmp.push("<tr><th valign='top'>HTML:</th><td  style='width:150px' valign='top'>&amp;#"+code+";<br>&amp;#x"+code.toString(16)+";");
  if (dct.html != ''){
    tmp.push('<br>&amp;'+dct.html+";");
  }
  tmp.push("</td>");
  tmp.push("<th valign='top' style='width:150px'>MathML:</th><td valign='top'>"+dct.mathml.join('<br>')+"</td></tr>");
  tmp.push("<tr><th valign='top'>TEX:</th><td valign='top'  class='entity_td_tex' colspan='3'>"+dct.tex+"</td></tr>");

  tmp.push('</table>');

  tmp.push('<ul>');
  tmp.push('<li>');
  switch (dct.xml){
    case 'name_start':
      tmp.push("can be used in names of XML elements and attributes including the first position");
      break;
    case 'name_in':
      tmp.push("can be used in names of XML elements and attributes but not as the first letter");
      break;
    case 'not_name':
      tmp.push("cannot be used in names of XML elements and attributes");
      break;
    default:
    tmp.push(dct.xml);
  }
    tmp.push('</li>');
  tmp.push('<li>');
  var chr = String.fromCharCode(code);
  switch (dct.uri){
    case 'escaped':
      tmp.push("must be escaped in URI as "+encodeURIComponent(chr));
      break;
    case 'unreserved':
      tmp.push("can be used in URI without restriction");
      break;
  case 'scheme_delimiter':
    tmp.push("this character has specific meaning in some protocols");
    tmp.push("; if the literal value is required it must be escaped as <b>"+encodeURIComponent(chr)+"</b>");
    break;
  case 'generic_delimiter':
    tmp.push(uri_generic_delimiter(chr));
    tmp.push("; if the literal value is required it must be escaped as <b>"+encodeURIComponent(chr)+"</b>");
    break;
    default:
    tmp.push(dct.uri);
  }
    tmp.push('</li>');
/*  if ((dct.uri == 'unreserved' || dct.uri == 'escaped') && dct.iri){
    tmp.push("<li>can be used in <a href='http://tools.ietf.org/html/rfc3987'>IRI</a> without restriction</li>");
  }*/

  tmp.push('</ul>');

  if (dct.digit != ''){
    tmp.push('<div style="font-weight:bold">Digit '+dct.digit+"  <span id='char_script'></span></div>");
    tmp.push(display_digits(dct.digit));
  }

  if (dct.similar != ''){
    tmp.push('<div style="font-weight:bold">Similar characters: <span id="char_script"></span></div>');
    tmp.push(display_similar(dct.similar,code));
  }

  output_text(tmp.join(''));
  location.hash=encodeURIComponent(code);

    $('span.display_char').hover(
    function(event){
      get_script_name(unicodeString2int($(event.target).attr('title')));
    },
    function(event){
    $('#char_script').html('&nbsp;');
    });
}

function image_div(code){
  var spriteStep = 128;
  var i = Math.floor(code/spriteStep);
  var style=['height:18px','width:18px'];
  var spriteURL = "sprites/"+i+".png";
  style.push('background-position:'+0+'px -'+(code%spriteStep * 18)+'px');
  style.push('background-image:url("'+spriteURL+'")');
  return "<div class='char' title='"+int2unicodeString(code)+"' style='"+style.join(';')+"'>&nbsp;</div>";

}

function display_script(event){
  var ls = scripts[$(event.target).attr('id')];
  var tmp = [];

  tmp.push("<h3>"+ls[0]+"</h3>");
  var rows = Math.ceil((ls[2] - ls[1])/10);
  tmp.push('<table><tr><td valign="top">');
  for (var i=ls[1]; i<=ls[2]; i++){
    tmp.push(image_div(i));
    if (((1+i-ls[1])%rows)==0){
      tmp.push('</td><td valign="top">');
    }
  }
  tmp.push('</td></tr></table>');
  output_text(tmp.join(''));
}

function display_keyword(event){
  var kw = $(event.target).html();
  for (var i=0; i<keywords.length; i++){
    if (keywords[i][0]==kw){
      var ls = keywords[i][1];
      break;
    }
  }

  var tmp = [];

  tmp.push("<div style='font-weight:bold;'>"+kw+"<span id='char_script'></span></div>");
  var rows = Math.ceil(ls.length/10);
  tmp.push('<table><tr><td valign="top">');
  for (var i=0; i<ls.length; i++){
    tmp.push(image_div(ls[i]));
    if (((1+i)%rows)==0){
      tmp.push('</td><td valign="top">');
    }
  }
  tmp.push('</td></tr></table>');
  output_text(tmp.join(''));
}

function output_text(txt){
  $('#char_output').html(txt);
  $('span.script_name').click(display_script);
  $('span.kw').click(display_keyword);
  $('.char').click(
    function(event){
      var code = unicodeString2int(($(event.target).attr('title')));
      display_charcode(code);
      var chr = String.fromCharCode(code);
      $('#char_input').val(chr);
    }
    );
  $('div.char').hover(
    function(event){
      get_script_name(unicodeString2int($(event.target).attr('title')));
    },
    function(event){
    $('#char_script').html('&nbsp;');
    });
}

function entity_table(ls){

}

function resolve_entity(nm){
  var tmp = [];
  var tmp2 = ["<table><tr>"];
  tmp.push("<h4>HTML:</h4>");
  var i = 0;
  $.map(htmlEntities,
    function(ls){
      if (nm == ls[0].slice(0,nm.length)){
	tmp2.push("<td style='width:80px; border:thin solid silver'>"+image_div(ls[1]));
	tmp2.push("<span class='char' title='"+int2unicodeString(ls[1])+"'>"+ls[0]+"</span></td>");
	i++;
	if (i!=0 && i%4==0){
	  tmp2.push('</tr><tr>');
	}
	 }
       });
  tmp2.push('</tr></table>');
  tmp.push(tmp2.join(''));

  tmp.push("<h4>MathML:</h4>");
  tmp2 = ["<table><tr>"];
  i = 0;
  $.map(mathmlEntities,
    function(ls){
      if (nm == ls[0].slice(0,nm.length)){
	tmp2.push("<td style='width:80px; border:thin solid silver'>"+image_div(ls[1]));
	tmp2.push("<span class='char' title='"+int2unicodeString(ls[1])+"'>"+ls[0]+"</span></td>");
	i++;
	if (i!=0 && i%4==0){
	  tmp2.push('</tr><tr>');
	}
	 }
       });
  tmp2.push('</tr></table>');
  tmp.push(tmp2.join(''));
  output_text(tmp.join(' '));
}

function display_similar(ls,code){
  var tmp=["<table cellpadding='0' cellspacing='0'><tr>"];
  var i = 0;

  $.map(ls,
	function(c){
	  if (i>0 && i%17==0){
	    tmp.push("</tr><tr>");
	  }
	  if (c!=code){
	    tmp.push("<td>"+image_div(c)+"</td>");
	    i++;
	    }
	}
       );
  tmp.push('</tr></table>');
  return tmp.join("");

}

function display_digits(d){
  var ls = digits[d];
  if (!ls){
    return "";
  }
  return display_similar(ls);
}

function resolve_keyword(nm){
  nm = nm.toUpperCase();
  var tmp = [];
  $.map(keywords,
       function(ls){
	 if (nm == ls[0].slice(0,nm.length)){
	   tmp.push("<span class='kw'>"+ls[0]+"</span>");
	 }
       });
  if (tmp.length>50) {
    tmp = tmp.slice(0,50);
    tmp.push('...');
  }
  output_text(tmp.join(', '));
  }

function resolve_script(nm){
  nm = nm.toUpperCase();
  var tmp = [];
  for (var a in scripts){
    var scr = scripts[a][0];
    if (scr.toUpperCase().match(nm)){
      tmp.push([scr,a]);
    }
  }
  tmp.sort();
  var out = [];
  $.map(tmp,
       function(scr){
	 out.push('<div><span class="script_name" id="'+scr[1]+'">'+scr[0]+"</span></div>");
       });
  output_text(out.join(''));
  }

  function get_script_name(i){
    for (var a in scripts){
      var ls = scripts[a];
      if (i>=ls[1] && i<=ls[2]){
	var script=ls[0];
	break;
      }
    }
    $('#char_script').html(script);
  }

function int2unicodeString(i){
  var str = i.toString(16).toUpperCase();
  str = "0000".slice(str.length) + str;
  return "U+"+str;
}

function unicodeString2int(txt){
  return parseInt(txt.slice(2),16);
}

function script_link(nm){
  return  "<span class='script_name' id='"+nm+"'>"+scripts[nm][0]+"</span></div>";
}

function chart_link(script){
  var url = "http://unicode.org/charts/PDF/"+script+".pdf";
  return "<div><a href='"+url+"'>"+url+"</a></div>";
}

function uri_generic_delimiter(chr){
  switch (chr) {
  case '?': return "starts <a target='_blank' href='http://tools.ietf.org/html/rfc3986#section-3.4'>query part</a> of URI";
  case '#': return "starts <a target='_blank' href='http://tools.ietf.org/html/rfc3986#section-3.5'>fragment part</a> of URI";
  case '/': return "separates <a target='_blank' href='http://tools.ietf.org/html/rfc3986#section-3.3'>path components</a> of URI; // starts <a target='_blank' href='http://tools.ietf.org/html/rfc3986#section-3.2'>authority component</a> of URI";
  case ':': return "starts <a target='_blank' href='http://tools.ietf.org/html/rfc3986#section-3.2.3'>protocol component</a> of URI";
  default: return "URI generic delimiter";
  }
}
