/**
 * Overall settings
 */

var article_spacing = 2000;


/**
 * Initialize the site.
 */
function init_site() {
  setup_size();

  var dim = Element.getDimensions($('body'));

  // Center the canvas
  $('canvas').style.top = (-10000 + dim.height / 2) + "px";
  $('canvas').style.left = (-10000 + dim.width / 2) + "px";

  prepare_contact_popup();

  // Make the canvas draggable
  new Draggable('canvas');

  Event.observe(window, 'resize', function() { setup_size(); });

  // Handle mousewheel scroll events for various browsers.
  Event.observe($('canvas'), "mousewheel", scroll_canvas, false);
  Event.observe($('canvas'), "DOMMouseScroll", scroll_canvas, false);

  Event.observe($('canvas'), "touchstart", touch_start, false);

  load_item(-1, 1);
  load_item(1, 1);
  load_item(1, -1);
  load_item(-1, -1);
  
  // Move to requested location, if any
  if (window.location.hash != "") {
    var coordinates = /^#(-*\d+),(-*\d+)/;
    var result = window.location.hash.match(coordinates);
    if (result != null) {
      goto_item(result[1], result[2]);
    }
  }
}

/**
 * Set up the size for the holder based on the window size
 */
function setup_size() {
  var dim = Element.getDimensions($('body'));
  $('holder').style.height = (dim.height - 68) + "px";
}

/**
 * Scroll the canvas based on the mousewheel
 */
function scroll_canvas(event) {
  canvas_move(0, 50 * Event.wheel(event));
}

/**
 * Handle touch events to move the canvas
 */
var startX = null;
var startY = null;
var endX;
var endY;

function touch_start(event) {
  // We don't want to interfere with links and other similar elements,
  // so only handle touch/drag on divs.
  if (event.target.tagName == 'DIV') {
    event.preventDefault();

    startX = event.targetTouches[0].pageX;
    startY = event.targetTouches[0].pageY;

    Event.observe($('canvas'), "touchmove", touch_move, false);
    Event.observe($('canvas'), "touchend", touch_end, false);
  }
}

function touch_move(event) {
  event.preventDefault();

  endX = event.targetTouches[0].pageX;
  endY = event.targetTouches[0].pageY;
}

function touch_end(event) {
  event.preventDefault();

  var move_x = endX - startX;
  var move_y = endY - startY;

  $('canvas').style.left = (parseFloat($('canvas').style.left) + move_x) + 'px';
  $('canvas').style.top  = (parseFloat($('canvas').style.top)  + move_y) + 'px';
  startX = null;
  startY = null;

  $('canvas').stopObserving("touchmove");
  $('canvas').stopObserving("touchend");
}


/**
 * Go to a specific grid location and show the associated content by
 * loading it on demand.
 */
function goto_item(x, y) {
  new Ajax.Request("/article/" + x + "/" + y,
                   {method:'get',
                       onSuccess: function(response) {
                       update_item(x, y, response.responseText, true);
                       _gaq.push(['_trackPageview', "/article/" + x + "/" + y]);
                     }
                   });
}

/**
  * Load a specific grid location and skip the navigate to part.
  * Quite equal to the above, other than the update_item has a false param
  */
function load_item(x, y) {
  new Ajax.Request("/article/" + x + "/" + y,
                   {method:'get',
                       onSuccess: function(response) {
                       update_item(x, y, response.responseText, false);
                     }                       
                   });
}

/** Center the canvas again
 */
function canvas_center() {
  var dim = Element.getDimensions($('body'));

  // Center the canvas
  var x = (-10000 + dim.width / 2);
  var y = (-10000 + dim.height / 2);

  canvas_move_to(x, y, null, null);
}

/**
 * Move canvas to absolute position, also updating mini canvas.
 */
function canvas_move_to(x, y, via_x, via_y) {
  new Effect.Move('canvas', { x: x, y: y, mode: 'absolute' });
  if (via_x && via_y) {
    new Effect.Move('canvas', { x: via_x, y: via_y, mode: 'absolute', queue:'front'});
  }
}

/**
 * Move canvas in relative direction, also updating mini canvas.
 */
function canvas_move(x, y) {
  var duration = 0.0;
  new Effect.Move('canvas', { x: x, y: y, duration: duration });
}


/**
 * Update or Create the specific grid item and move to it afterwards
 */
function update_item(x, y, text, navigate) {
  var item_id = "item_" + x + "_" + y;
  if ($(item_id)) {
    alert("Item already exists, updating");
  } else {
    var new_x = 10000 + x * article_spacing;
    var new_y = 10000 + -y * article_spacing;
    var item = new Element('div',
                           {'class':'article',
                            'style':"top:"+new_y+"px;left:"+new_x+"px"}).update(text);
    Element.insert($('canvas'), item);
    external_links();

    if(navigate){
      var dim = Element.getDimensions(item);
      canvas_move_to(-new_x + 10, -new_y + 15, -new_x + 10, -new_y + 75 - (dim.height/2));
    }
  }

}


/**
 * here_x, here_y: determine where we are right now based on actual
 * canvas coordinates.
 */
function here_x() {
  return Math.round(($('canvas').offsetLeft + 10000) / -article_spacing);
}
function here_y() {
  return Math.round(($('canvas').offsetTop + 10000) / article_spacing);
}

/**
 * Mouse wheel extension from http://www.ogonek.net/mousewheel/demo.html
 */
Object.extend(Event, {
	wheel:function (event){
		var delta = 0;
		if (!event) event = window.event;
		if (event.wheelDelta) {
			delta = event.wheelDelta/120; 
			if (window.opera) delta = -delta;
		} else if (event.detail) { delta = -event.detail/3;	}
		return Math.round(delta); //Safari Round
	}
});


/**
 * Switch the navigation module from search to navigation and vice versa.
 */
function switch_navigation(from, to) {
  new Effect.Fade(from);
  new Effect.Appear(to);
}


/**
 * Show an arrow to the next article on the canvas in this direction, if any.
 */
function show_next_arrow(event) {
  var next = $(event.target.id);

  var x = next_x(event.target.id);
  var y = next_y(event.target.id);

  next.href="#" + x + "," + y;
  next.onclick = function() {
    goto_item(x, y);
  }

  new Effect.Opacity(next, { to: 0.5 });
}

function hide_next_arrow(event) {
  var next = $(event.target.id);

  new Effect.Opacity(next, { to: 0.0 });
}

function next_x(next_id) {
  var x = here_x();

  if (next_id == "next-left") {
    x = x - 1;
  }
  if (next_id == "next-right") {
    x = x + 1;
  }

  return x;
}

function next_y(next_id) {
  var y = here_y();

  if (next_id == "next_top") {
    y = y + 1;
  }
  if (next_id == "next_bottom") {
    y = y - 1;
  }

  return y;
}


/* Navigation aides */
function navigation_pull_up() {
  $('pull-up').hide();
  $('push-down').show();

  Effect.BlindDown('pull-up-content');
}

function navigation_push_down() {
  Effect.BlindUp('pull-up-content');

  $('push-down').hide();
  $('pull-up').show();
}

