// debug - v0.3 - 6/8/2009
// http://benalman.com/projects/javascript-debug-console-log/
window.debug=(function(){var c=this,e=Array.prototype.slice,b=c.console,i={},f,g,j=9,d=["error","warn","info","debug","log"],m="assert clear count dir dirxml group groupEnd profile profileEnd time timeEnd trace".split(" "),k=m.length,a=[];while(--k>=0){(function(n){i[n]=function(){j!==0&&b&&b[n]&&b[n].apply(b,arguments)}})(m[k])}k=d.length;while(--k>=0){(function(n,o){i[o]=function(){var q=e.call(arguments),p=[o].concat(q);a.push(p);h(p);if(!b||!l(n)){return}b.firebug?b[o].apply(c,q):b[o]?b[o](q):b.log(q)}})(k,d[k])}function h(n){if(f&&(g||!b||!b.log)){f.apply(c,n)}}i.setLevel=function(n){j=typeof n==="number"?n:9};function l(n){return j>0?j>n:d.length+j<=n}i.setCallback=function(){var o=e.call(arguments),n=a.length,p=n;f=o.shift()||null;g=typeof o[0]==="boolean"?o.shift():false;p-=typeof o[0]==="number"?o.shift():n;while(p<n){h(a[p++])}};return i})();
var report = debug.log;  // mirrors Flash

$(document).ready(function() {
  $('#admin_console_border').mousedown(beginDrag);
  $(window).keydown(hideConsole);
  if(!developing && !$('#original_recipe').hasClass('no_recipe'))
    setTimeout(startRecipes, 1000);
});

var recipeCount = 0;
var recipeTimer;
function startRecipes()
{
  originalRecipe();
  recipeTimer = setInterval(originalRecipe, 5*60*1000);
}

function originalRecipe()
{
  if(++recipeCount >= 6)
    clearInterval(recipeTimer);
  else if(!recipeTimer)
    recipeTimer = setInterval(originalRecipe, 5*60*1000);
  $.getJSON("/recipe", function(recipe) {
    $('#original_recipe').html(recipe.recipe).attr("title", recipe.source);
  });
}

function makeIntoOneLine(elem)
{
  var height = elem.offsetHeight;
  var text = elem.innerHTML;
  elem.innerHTML = 'test';
  var normheight = elem.offsetHeight;
  elem.innerHTML = text;
  return shortenTextInElem(elem, normheight);
}

function shortenTextInElem(elem, targetheight) {
  var text = elem.innerHTML;
  var height = elem.offsetHeight;
  if (height > targetheight) {
    if (elem.title == '')
      {
    elem.title = text.replace(/(<([^>]+>))/ig, "");
    $(elem).data('full', text);
      }
    var words = text.split(' ');
    words.pop();
    text = words.shift();
    while(words.length != 0) {
      var word = words.shift();
      elem.innerHTML = text+' '+word+' ...';
      if (elem.offsetHeight > targetheight)
    break;
      text += ' '+word;
    }
    text += ' ...';
  }
  var same = elem.innerHTML = text;
  elem.innerHTML = text;
  return (height > targetheight && !same);
}

function makeGroupSingleLined(objects) {
  var has_multilines = true;
  var cycles = 0;
  while (has_multilines) {
    has_multilines = false;
    for (var i=0; i<objects.length; i++)
      if (makeIntoOneLine(objects[i]))
    has_multilines = true;
    cycles += 1;
    if (cycles > objects.length) break;
  }
}


function RGBtoHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B);}
function toHex(N) {
 if (N==null) return "00";
 N=parseInt(N); if (N==0 || isNaN(N)) return "00";
 N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N);
 return "0123456789ABCDEF".charAt((N-N%16)/16)
      + "0123456789ABCDEF".charAt(N%16);
}

function HexToR(h) {return parseInt((cutHex(h)).substring(0,2),16);}
function HexToG(h) {return parseInt((cutHex(h)).substring(2,4),16);}
function HexToB(h) {return parseInt((cutHex(h)).substring(4,6),16);}
function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7) : h;}

function switchToInnerTab(windowid, newtab, windowcontainer) {
  var sclass = "selectedinnertab";
  $('#innertabs div.'+sclass).removeClass(sclass);
  $(newtab).addClass(sclass);

  $('div.window', windowcontainer).addClass("hidden");
  $('#'+windowid).removeClass("hidden");
}

function makeUVLPParams(q) {
  var params = {};
  if(q.charAt(0) == "?") q = q.substr(1);
  jQuery.each(q.split('&'), function()
    {
      params[this.split('=')[0]] = this.split('=')[1];
    });
  return params;
}

function isAE500(response)
{
  return response.length > 300 && response.indexOf("The server encountered an error and could not complete your request.") != -1;
}

$.retried_ajax = function(type, url, data, success, delay) {
  delay = delay || 200;  // start retries at 200ms, doubling each time
  if(delay >= 1200000)
    return;  // no response after twenty minutes? quit (show giveup error msg?)
  if(!data) { // no extra params passed
    data = {};
    success = function() {};
  }
  else if(!success) { // missing success
    success = data;
    data = {};
  }

  $[type](url, data, function(response) {
    if(response == "timeout" || response == "retry" || isAE500(response))
      setTimeout(function() { $.retried_ajax(type,url,data,success,delay*2); },
         delay);
    else if (response == "disabled") {
      window.location.href = '/disabled';
    }
    else
      success(response);
  });
};

// If you use two args, the second is treated as the success function instead.
// You can also just pass the URL.
$.retried_get = function(url, data, success) {
  $.retried_ajax("get", url, data, success);
};

$.retried_post = function(url, data, success) {
  $.retried_ajax("post", url, data, success);
};


function inversePct(num, total) {
  return parseInt((100 * (total - num)) / total) + "%";
}


function removeScreen() { $("#screen").fadeOut(500); }
function replaceScreen() { $("#screen").fadeIn(500); }

function logServerError(e) {
  var params = {'message':e.message,
        'fileName':e.fileName,
        'lineNumber':e.lineNumber,
        'stack':e.stack,
        'name':e.name};
  $.retried_get("j_error", params, function() {});
  debug.error("error!: ", params);
}


function clickWithin(e) {
  var jelem = $(e.target);
  if (jelem.hasClass("parent_clicker")) $('*',jelem).click();
}



// Admin console controls

var offsetX = 0;
var offsetY = 0;

function beginDrag(e) {
  var console = $('#admin_console');
  offsetX = e.pageX - parseInt(console.css('left'));
  offsetY = e.pageY - parseInt(console.css('top'));
  $('body').mousemove(drag).mouseup(endDrag);
  /*
  var pageCoords = "( " + e.pageX + ", " + e.pageY + " )";
  var clientCoords = "( " + e.clientX + ", " + e.clientY + " )";
  debug.log("( B e.pageX, e.pageY ) - " + pageCoords);
  debug.log("( B e.clientX, e.clientY ) - " + clientCoords);
   */
}

function drag(e) {
  /*
  var pageCoords = "( " + e.pageX + ", " + e.pageY + " )";
  var clientCoords = "( " + e.clientX + ", " + e.clientY + " )";
  debug.log("( D e.pageX, e.pageY ) - " + pageCoords);
  debug.log("( D e.clientX, e.clientY ) - " + clientCoords);
  */
  $('#admin_console')
    .css('left',e.pageX-offsetX+'px')
    .css('top',e.pageY-offsetY+'px');
}

function endDrag(e) {
  saveConsoleSettings();
  $('body').unbind("mousemove", drag).unbind("mouseup", endDrag);
}

function hideConsole(e) {
  if (e.keyCode==33 && e.shiftKey==1) {
    var console = $('#admin_console');
    console.toggleClass('hidden');
    saveConsoleSettings();
  }
}

function saveConsoleSettings() {
  var console = $('#admin_console');
  if (!console.is('*')) return;
  var params = { left:console.css('left'),
         top:console.css('top'),
             hidden:console.hasClass('hidden') };
  $.retried_get("/admin/saveconsoleparams",params,function() { ; });
}



//var to_replace = [['C','Character'],['D','Definition'],['T','Tone'],
//        ['P','Pinyin'],   ['K','Kanji'],     ['R','Reading']];
//for (var i=0; i<to_replace.length; i++)
//  to_replace[i][1] = ('<span title="'+to_replace[i][1]+'">'+
//            to_replace[i][0]+'</span>');

var part_map = {
  C:'Character', D:'Definition', T:'Tone',
  P:'Pinyin',    K:'Kanji',      R:'Reading'
};

function addPartTitles(elems) {
  elems.each(function()
  {
    var cell = $(this);
    var html = cell.html();
    if (html.indexOf('span')>-1) return true;
    cell.attr('title',part_map[$.trim(html)]);
    //for (var i=0; i<to_replace.length; i++)
      //html = html.replace(to_replace[i][0], to_replace[i][1]);
    //cell.html(html);
    return true;
  });
}


function log(s) {
  var t = $('#admin_console textarea');
  if (t.length==0) return;
  if (t.hasClass('hidden')) {
    t.val('');
    t.removeClass('hidden');
  }
  t.val(s+'\n'+t.val());
}


function findParent(elem, key_func) {
  elem = $(elem)[0];
  try { while (!key_func(elem)) elem = elem.parentNode; }
  catch (e) { return null; }
  return elem;
}

function textToHTML(s, author) {
 //var old_s = s;
 s = $('<div>').html(s).text();  // strip the HTML
 s = s.replace(/img:(http:\/\/\S+)/gi, '<img src="$1"/>')  // img:http://...
   .replace(/\n/gi, '<br/>')                        // newlines
   .replace(/\*([^*]+)\*/gi, '<b>$1</b>')           // *bolds* it
   .replace(/_([^ _][^_]*)_/gi, '<em>$1</em>');     // _italicizes_ it
 //debug.info(old_s, "\n->\n", s);
 if(author)
   s = s + '<span class="other_mnem_byline"> ('+author+')</span>';
 return s;
}

function HTMLToText(s) {
  s = s.replace(/<img src="(http:\/\/\S+)"\/?>/gi, 'img:$1')
    .replace(/<br\/?>/gi, '\n')
    .replace(/<b>(.*?)<\/b>/gi, '*$1*')
    .replace(/<em>(.*?)<\/em>/gi, '_$1_')
    .replace(/<span class="other_mnem_byline">.*?<\/span>/gi, '');
  return s;
}

// http://www.vanyli.net/?p=3
// could extend this to retry timeouts with a failure func, too
$.delayed_ajax = function(options) {
  options.tstamp = (new Date().getTime() + new Date().getMilliseconds());
  options.success_original = options.success;
  options.success = function(data, status) {
    var last = $('body').data('ajax_pool' + options.request_type);
    if (last.tstamp == options.tstamp && options.success_original)
       options.success_original(data, status);
  };

  $('body').data('ajax_pool' + options.request_type, options);

  if ($('body').data('timeout_pool' + options.request_type))
    clearTimeout($('body').data('timeout_pool' + options.request_type));

  $('body').data('timeout_pool' + options.request_type,
         setTimeout("do_request('" + options.request_type + "')",
                 options.delay));

  do_request = function(request_type) {
    $.ajax($('body').data('ajax_pool' + request_type));
  };
};

/*
 * POP UPS (to replace dialogs)
 *
 * To create a popup, pass in the url and params for the popup's body,
 * and the parent popup if there is one.
 *
 * Things like locking and callbacks are done with the javascript object.
 *
 */

function Popup(url, params) {

  // PROPERTIES

  this.callback = null;
  this.ret_val = null;
  this.parent = null; // Javascript Object
  this.child = null; // Javascript Object
  this.jqobj = null; // jQuery Object
  this.locked = false;
  this.url = null;
  this.params = null;

  // FUNCTIONS

  this.setCallback = function(callback) {
    this.callback = callback;
    return this;
  };

  this.mouseClick = function(e) {
    //debug.info('mouse click callback');
    // this function gets called whenever the mouse is clicked when a popup
    // is open
    var popup = findParent(e.target, function(elem)
    {
      return $(elem).hasClass('popup') || $(elem).hasClass('popup_button');
    });
    if (popup==null) {
      // outside of any popup, need to close it
      popup = $('.root_popup');
      if (popup.length==0)
    $('body').unbind('click', this.mouseClick);
      else
    popup.data('j_obj').close();
    }
    else {
      // inside a popup, close any child popups
      var j_obj = $(popup).data('j_obj');
      if (j_obj==null) return;
      var child = j_obj.child;
      if (child!=null) child.close();

      if ($(e.target).hasClass('popup_close'))
    j_obj.close();
    }
  };

  this.openOnPage = function() {
    $('#popup_screen').height($(document).height());
	//debug.info('put this as body height: ',$(document).height());
	$(window).resize(function () {
						 $('#popup_screen').height($(document).height());
					   }); // ensures that the screen covers eeeeeeverything!
    // inserts this popup in the page, so not nested in any other popups
    this.jqobj.addClass('root_popup');
    $('#popup_screen').show();
    $('#popup_wrapper').show().append(this.jqobj);
    $('body').click(this.mouseClick);
    return this;
  };

  this.openInPopup = function(parent_popup) {
    // puts this popup, nested in another popup
    this.jqobj.addClass('child_popup');
    if (!this.jqobj.hasClass('inner_node_popup') &&
    !this.jqobj.hasClass('leaf_node_popup'))
      this.jqobj.addClass('leaf_node_popup');
    $(parent_popup).append(this.jqobj);
    this.parent = $(parent_popup).data('j_obj');
    this.parent.child = this;
    return this;
  };

  this.showNav = function(parent_popup) {
    this.jqobj.find('.popup_nav').removeClass('hidden');
    return this;
  };

  this.open = function(parent_popup) {
    if (parent_popup==null) return this.openOnPage();
    else return this.openInPopup(parent_popup);
  };

  this.close = function() {
    //debug.info('close');
    // closes this popup, calling any callback with any return value
    // that has been set prior to the closing to the callback and ret_val
    // values
    if (this.callback!=null) {
      try { this.callback(this.ret_val); }
      catch (e) { ; }
    }

    if (this.jqobj.hasClass('root_popup')) {
      $(window).unbind('resize');
	  $('#popup_screen').hide();
      $('#popup_wrapper').hide().html('');
      $('body').unbind('click', this.mouseClick);
    }

    this.jqobj.remove();
    return this;
  };

  this.lock = function() {
    // Makes it so that you can't close this popup with clicks outside
    // the box or with the remove button
    $('.popup_close', this.jqobj).hide();
    $('body').unbind('click', this.mouseClick);
    this.locked = true;
    return this;
  };

  this.positionFromTop = function(pageY) {
    var top = Math.max(pageY-474, 0);
    this.jqobj.css('top',top+'px');
    return this;
  };

  this.loadUrl = function(url, params) {
    if (!params) params = {};
    this.url = url;
    this.params = params;

    $.retried_get(url, params, function(popup, url, params) {
      return function(response)
    {
      if (popup.url!=url || popup.params!=params) return;
      $('.popup_body', popup.jqobj).remove();
      $('.popup_loading', popup.jqobj).remove();
      $('.popup_bar', popup.jqobj)
        .after($(response).addClass('popup_body'));
      if (popup.locked) $('input[value="Cancel"]', popup.jqobj).hide();
    };
    } (this, url, params)
    );
  };

  this.setAsInnerNode = function() {
    //makeFullWidth
    this.jqobj.removeClass('leaf_popup');
    this.jqobj.addClass('inner_node_popup');
    return this;
  };

  // INITIALIZATION

  this.jqobj = $('#blank_popup .popup').clone();
  this.jqobj.data('j_obj',this);

  this.loadUrl(url, params);
}

function findParentPopup(elem) {
  debug.info(elem);
  var key = function(elem) { return $(elem).hasClass('popup'); };
  debug.info($(findParent(elem, key)));
  return $(findParent(elem, key)).data('j_obj');
}

function closeParentPopup(elem) {
  findParentPopup(elem).close();
}


/* CANVAS BUTTON? */

function makeCanvasButton(div) {
  // figure out the width and height of the div and lock it in place
  var height = div.css('height');
  var width  = div.css('width');
  div.attr('height',height).attr('width',width);
  height = parseInt(height);
  width  = parseInt(width);
  debug.info(width);
  debug.info(height);
  var radius = 5;

  // make a canvas element and add it to the div
  var canvas = $('<canvas width='+width+' height='+(height*3)+'></canvas>');
  div.prepend(canvas);

  // for testing purposes just make three rectangles
  debug.info(canvas);
  var ctx = canvas[0].getContext('2d');
  roundedRect(ctx, 0, 0, width, height, 5);
  ctx.fillStyle = "rgb(255,0,0)";
  ctx.fillRect(0,0,width,height);
  ctx.fillStyle = "rgb(0,255,0)";
  ctx.fillRect(0,height,width,height*2);
  ctx.fillStyle = "rgb(0,0,255)";
  ctx.fillRect(0,height*2,width,height*3);

}

function roundedRect(ctx,x,y,width,height,radius){
  ctx.beginPath();
  ctx.moveTo(x,y+radius);
  ctx.lineTo(x,y+height-radius);
  ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
  ctx.lineTo(x+width-radius,y+height);
  ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
  ctx.lineTo(x+width,y+radius);
  ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
  ctx.lineTo(x+radius,y);
  ctx.quadraticCurveTo(x,y,x,y+radius);
}
