var _collage, _zoomed;
var _form, _upload, _fake_upload_button, _pict_upload, _pict_iframe, _status;
var _x, _y, _w, _h, _wp, _hp, _lock, _center;
var _alpha;
var _clip, _clipButton, _clipMore;
var _zooms, _zoomButton, _zoomMore;
var _undo, _redo, _undoButton, _redoButton, _undoMore, _redoMore;

var graphics;
var graphics_zoom;
var min_size = 10;
var picture = null;
var collage_picture = null;

var showExtras = true;

var black = 'rgb(0,0,0)';
var red = 'rgb(255,0,0)';
var green = 'rgb(0,255,0)';
var blue = 'rgb(0,0,255)';
var black = 'rgb(0,0,0)';
var gray = 'rgb(150,150,150)';
var white = 'rgb(255,255,255)';
var frameColor = black;

var clipSelectionMode = false;

var isIE = false;

function Properties() {
  this.pos = new Point(0, 0);
  this.dim = new Dimension(picture.width, picture.height);
  this.lock_ratio = picture.width / picture.height;
  this.lock_ratio_perc = 1;
  this.locked = false;
  this.centered = false;
  this.alpha = 100;
  this.clip = new Array();
  this.restore = Properties_restore;
  this.toString = Properties_toString;
  this.equals = Properties_equals;
  this.change = Properties_change;
}
function Properties_restore() {
  _x.value = this.pos.x;
  _y.value = this.pos.y;
  _w.value = this.dim.w;
  _h.value = this.dim.h;
  _lock.checked = this.locked;
  changeClass(_lock, 'down', _lock.checked);
  _center.checked = this.centered;
  changeClass(_center, 'down', _center.checked);
  _wp.value = this.dim.w*100/picture.width;
  _hp.value = this.dim.h*100/picture.height;
  _alpha.value = this.alpha;
  recreateClipPoints();
  redraw();
}
function Properties_toString() {
  var str = '<td>'+this.pos+'</td><td>'+this.dim+'</td><td>'+this.alpha+'%</td><td>';
  if (this.clip.length == 0)
    str += 'None</td>';
  else
    str += '<span title="'+this.clip+'" class=over>Clipped</span></td>';
  return str;
}
function Properties_change(p) {
  if (this.dim.w != p.dim.w || this.dim.h != p.dim.h)
    return "resizing to " + this.dim;
  if (this.pos.x != p.pos.x || this.pos.y != p.pos.y)
    return "moving to " + this.pos;
  if (this.alpha != p.alpha)
    return "setting opacity to " + this.alpha + "%";
  if (this.clip.join() != p.clip.join()) {
    if (this.clip.length == p.clip.length)
      for (var i = 0; i < this.clip.length; i++)
        if (!this.clip[i].equals(p.clip[i]))
          return 'changing clip point from ' + p.clip[i] + ' to ' + this.clip[i];
    var added = this.clip.length > p.clip.length;
    for (var i = 0; i < Math.min(this.clip.length, p.clip.length); i++)
      if (!this.clip[i].equals(p.clip[i]))
        return (added?'adding':'removing')+' clip point ' + this.clip[i];
    if (added)
      return 'adding clip point ' + this.clip[this.clip.length-1];
    return 'removing clip point ' + p.clip[p.clip.length-1];
  }
  if (this.locked != p.locked || this.lock_ratio != p.lock_ratio)
    return "locking proportions";
  if (this.centered != p.centered)
    return "resizing around center";
}
function Properties_equals(p) {
  return this.pos.equals(p.pos) && this.dim.equals(p.dim) &&
         this.lock_ratio==p.lock_ratio && this.locked==p.locked && this.centered==p.centered &&
         this.alpha==p.alpha && this.clip.join()==p.clip.join();
}

var inited =false;
if (document.addEventListener)
  document.addEventListener("DOMContentLoaded", init, false)

function init() {
  inited = true;
  $('jsdisabled').style.display = 'none';

  _collage = $('collage'); _zoomed = $('zoomed');
  _collage.dim = new Dimension(_collage.width, _collage.height);
  _form = $('form'); _upload = $('upload'); _fake_upload_button = $('fake_upload_button');
  _pict_iframe = frames['picture_upload'];
  _status = $('status');
  _zooms = $('zooms'); _zoomButton = $('zoomButton'); _zoomMore = $('zoomMore');
  _undo = $('undo'); _redo = $('redo');
  _undoButton = $('undoButton'); _redoButton = $('redoButton');
  _undoMore = $('undoMore'); _redoMore = $('redoMore');

  _x = $('x'); _y = $('y'); _w = $('width'); _h = $('height'); _wp = $('widthperc'); _hp = $('heightperc');
  _lock = $('lock'); _center = $('center');
  _clip = $('clip'); _clipButton = $('clipButton'); _clipMore = $('clipMore');
  _alpha = $('alpha');
  
  if (!_collage.getContext){
    $('canvasdisabled').style.display = '';
    return;
  }
  $('disabled').style.display = 'none';
  $('enabled').style.display = '';
  graphics = _collage.getContext('2d');
  graphics_zoom = _zoomed.getContext('2d');
  if (window.opera) { //Opera has a problem with hidden images
    collage_picture = new Image(); collage_picture.src = $('collage_picture').src;
  } else
    collage_picture = $('collage_picture');
  collage_picture.onload = function (e) {
    if (picture && picture.loaded) redraw(e);
    else graphics.drawImage(collage_picture, 0, 0, collage_picture.width, collage_picture.height);
  }

  _upload.onchange = changePicture;
  _upload.onmouseover = function (e) { addClass(_fake_upload_button,'hilight'); }
  _upload.onmouseout = function (e) { removeClass(_fake_upload_button,'hilight'); }
  _upload.onmousedown = function (e) { addClass(_fake_upload_button,'down'); removeClass(_fake_upload_button,'highlight'); }
  _upload.onmouseup = function (e) { addClass(_fake_upload_button,'hilight'); removeClass(_fake_upload_button,'down'); }
  _fake_upload_button.onclick = function (e) { return false; }
  
  $('addIt').onclick = addIt;

  document.onmousedown = startAction;
  document.onmousemove = updateAction;
  document.onmouseup = endAction;
  document.onkeydown = keyDown;
  document.onkeyup = keyUp;
  document.onkeypress = keyPress;
  document.oncontextmenu = contextMenu;

  _x.onchange = _y.onchange = redraw;
  _w.onchange = _h.onchange = redraw;
  _wp.onchange = _hp.onchange = changeSizePerc;
  _lock.onclick = locking;
  _center.onclick = centering;
  _alpha.onchange = redraw;
  _clipButton.onclick = switchClipSelectionMode;
  _clipMore.onclick = function (e) { showMenu(_clip, _clipMore); return false; }
  
  _zoomButton.onclick = function (e) { return false; }
  _zoomMore.onclick = function (e) { showMenu(_zooms, _zoomMore); return false; }
  _zooms.rows[0].cells[0].onclick = createZoomFunction(1, 0);
  _zooms.rows[1].cells[0].onclick = createZoomFunction(1.5, 1);
  _zooms.rows[2].cells[0].onclick = createZoomFunction(2, 2);
  _zooms.rows[3].cells[0].onclick = createZoomFunction(2.5, 3);
  _zooms.rows[4].cells[0].onclick = createZoomFunction(3, 4);
  _zooms.rows[5].cells[0].onclick = createZoomFunction(4, 5);
  _zooms.rows[6].cells[0].onclick = createZoomFunction(5, 6);
  
  _undoButton.onclick = function (e) { undo(); return false; }
  _redoButton.onclick = function (e) { redo(); return false; }
  _undoMore.onclick = function (e) { showMenu(_undo, _undoMore); return false; }
  _redoMore.onclick = function (e) { showMenu(_redo, _redoMore); return false; }
  
  $('helpButton').onclick = function(e) { toggleClass($('helpButton'), 'down'); toggleDisplay($('help')); return false; }
  
  _form.onreset = resetValues;
  _form.reset();
}

function createZoomFunction(level, index) {
  return function (e) {
    zoom_amount = level;
    for (var i = 0; i < _zooms.rows.length; i++) {
      if (i != index) removeClass(_zooms.rows[i], 'down');
      else               addClass(_zooms.rows[i], 'down');
    }
    redraw(e);
    return false;
  };
}

var p = null;
var redos = new Array();
var undos = new Array();
function saveUndo() {
  if (undos.length > 0 && p.equals(undos[undos.length-1]))
    return;
  var state = copyObject(p);
  undos.push(state);
  redos.length = 0;
  if (undos.length > 1) {
    removeClass(_undoButton.parentNode, 'disabled');
    var str = "Undo " + undos[undos.length-1].change(undos[undos.length-2]);
    _undoButton.title = str + " (Ctrl+Z)";
    setupUndoRow(_undo.tBodies[0].insertRow(0), str, false);
  } else {
    addClass(_undoButton.parentNode, 'disabled');
    _undoButton.title = "Cannot Undo (Ctrl+Z)";
  }
  while (_redo.tBodies[0].rows.length != 0)
    _redo.tBodies[0].deleteRow(0);
  _redoButton.title = "Cannot Redo (Ctrl+X)";
  addClass(_redoButton.parentNode, 'disabled');
}
function undo() {
  if (undos.length > 1) {
    redos.push(undos.pop());
    setupUndoRow(_redo.tBodies[0].insertRow(0), _undo.tBodies[0].rows[0].innerHTML.replace('Undo','Redo'), true);
    _undo.tBodies[0].deleteRow(0);
    if (undos.length > 1) {
      removeClass(_undoButton.parentNode, 'disabled');
      _undoButton.title = "Undo " + undos[undos.length-1].change(undos[undos.length-2]) + " (Ctrl+Z)";
    } else {
      addClass(_undoButton.parentNode, 'disabled');
      _undoButton.title = "Cannot Undo (Ctrl+Z)";
    }
    removeClass(_redoButton.parentNode, 'disabled');
    _redoButton.title = "Redo " + redos[redos.length-1].change(undos[undos.length-1]) + " (Ctrl+X)";
  }
  p = copyObject(undos[undos.length-1]);
  p.restore();  
}
function redo() {
  if (redos.length == 0) return;
  var state = redos.pop();
  undos.push(state);
  setupUndoRow(_undo.tBodies[0].insertRow(0), _redo.tBodies[0].rows[0].innerHTML.replace('Redo','Undo'), false);
  _redo.tBodies[0].deleteRow(0);
  removeClass(_undoButton.parentNode, 'disabled');
  _undoButton.title = "Undo " + undos[undos.length-1].change(undos[undos.length-2]) + " (Ctrl+Z)";
  if (redos.length > 0) {
    removeClass(_redoButton.parentNode, 'disabled');
    _redoButton.title = "Redo " + redos[redos.length-1].change(undos[undos.length-1]) + " (Ctrl+X)";
  } else {
    addClass(_redoButton.parentNode, 'disabled');
    _redoButton.title = "Cannot Redo (Ctrl+X)";
  }
  p = copyObject(state);
  p.restore();
}
function setupUndoRow(row, text, isRedo) {
  row.appendChild(document.createTextNode(text));
  if (isRedo) row.onclick = function() { var c=row.rowIndex+1; for (var i=0; i<c; i++) redo(); };
  else        row.onclick = function() { var c=row.rowIndex+1; for (var i=0; i<c; i++) undo(); };
}
function clearUndos() {
  undos.length = 0;
  while (_undo.tBodies[0].rows.length != 0)
    _undo.tBodies[0].deleteRow(0);
  _undoButton.title = "No Undos Available (Ctrl+Z)";
  addClass(_undoButton.parentNode, 'disabled');
  redos.length = 0;
  while (_redo.tBodies[0].rows.length != 0)
    _redo.tBodies[0].deleteRow(0);
  _redoButton.title = "No Redos Available (Ctrl+X)";
  addClass(_redoButton.parentNode, 'disabled');
}

function resetValues() {
  _status.style.display = '';
  $('inputs').style.display = 'none';
  _zoomed.style.display = 'none';
  picture = null;
  p = null;
  clearUndos();
  _x.value = _y.value = _w.value = _h.value = 0;
  _wp.value = _hp.value = 100;
  _lock.checked = _center.checked = false;
  removeClass(_lock, 'down');
  removeClass(_center, 'down');
  removeClass(_clipButton, 'down');
  if (activeMenu) {
    activeMenu.style.display = 'none';
    if (activeMenuBut) removeClass(but, 'down');
    activeMenuBut = activeMenu = null;
  }
  while (_clip.rows.length != 0)
    _clip.tBodies[0].deleteRow(0);
  _alpha.value = 100;
  if (graphics)
    graphics.drawImage(collage_picture, 0, 0, collage_picture.width, collage_picture.height);
}
function changePicture(e) {
  resetValues();
  _status.innerHTML = '<span class=good>Loading image...</span>';
  _form.submit();
  loadPicture();
}
function loadPicture() {
  if (_pict_iframe.document.body.innerHTML.indexOf('XXX') == -1) {
    setTimeout('loadPicture()',16);
    return;
  }
  var text = _pict_iframe.document.body.innerHTML.replace(/<.*?>/g, "").replace(/XXX/g, "");
  _pict_iframe.document.body.innerHTML = '';
  if (text.indexOf('Error:') == -1) {
    resetValues();
    picture = new Image();
    picture.src = "picture.php?id=" + text + (isIE?'&IE=1':'');
    picture.loaded = false;
    picture.onload = pictureLoaded;
  } else
    _status.innerHTML = '<span class=error>'+text+'</span>';
}
function pictureLoaded(e) {
  p = new Properties(picture);
  picture.loaded = true;
  _status.innerHTML = '';
  _status.style.display = 'none';
  $('inputs').style.display = '';
  _zoomed.style.display = '';
  _upload.blur();
  saveUndo();
  redraw(e);
}

var outside = -1;
var none = 0;
var N = 1;
var E = 2;
var S = 4;
var W = 8;
var NE = N | E; //3
var SE = S | E; //6
var NW = N | W; //9
var SW = S | W; //12
var middle = 16;

function getRegion(e) {
  var pos = getPos(_collage);
  if (!pos || !p.pos || getTarget(e) != _collage) return outside;
  pos = getMousePos(e).difference(pos);
  var dim = _collage.dim;
  if (pos.x < 0 || pos.y < 0 || pos.x > dim.w || pos.y > dim.h)
    return outside;
  pos = pos.difference(p.pos);
  dim = p.dim;
  var o = 10;
  var i = 5;
  if (pos.x < -o || pos.y < -o || pos.x > dim.w+o || pos.y > dim.h+o)
    return none;
  else if (pos.x > i && pos.y > i && pos.x < dim.w-i && pos.y < dim.h-i)
    return middle;
  else if (pos.x <= i) { //handle all WEST
    if (pos.y <= i)       return NW;
    if (pos.y >= dim.h-i) return SW
    return W;
  } else if (pos.x >= dim.w-i) { //handle all EAST
    if (pos.y <= i)       return NE;
    if (pos.y >= dim.h-i) return SE;
    return E;
  } else if (pos.y <= i) //handle NORTH/SOUTH
    return N;
  else
    return S;
}

var a_none = 0;
var a_drag = 1;
var a_resize = 2;
var a_alpha = 3;

var action = a_none;

function startAction(e) {
  if (p == null) return;
  if (action != a_none) return false;
  if (!e) e = window.event;
  var region = getRegion(e);
  if (region == outside) return;
  if (clipSelectionMode) {
    setClipPoint(e);
  } else switch (region) {
    case N: case E: case S: case W: case NW: case NE: case SW: case SE: 
      resize_start(e, region);
      action=a_resize;
      return false;
    case middle:
      drag_start(e);
      action = a_drag;
      return false;
    default:
  }
}

var justOutside = true;

function updateAction(e) {
  if (p == null) return;
  if (!e) e = window.event;
  var region = getRegion(e);
  if (region == outside) {
    if (justOutside)
      redraw(e);
    justOutside = false;
    return;
  }
  justOutside = true;
  var collageRelPos = getMousePos(e).difference(getPos(_collage));
  var pictureRelPos = collageRelPos.difference(p.pos);
  window.status = "Mouse position in collage: " + collageRelPos + ", Mouse position in picture: " + pictureRelPos;
  switch (action) {
    case a_drag: drag_update(e); break;
    case a_resize: resize_update(e); break;
    case a_alpha: alpha_update(e); break;
    default: updateCursor(e, region);
  }
  redraw(e);
  return false;
}
function endAction(e) {
  if (p == null) return;
  if (action != a_none) {
    saveUndo();
    action = a_none;
    return false;
  }
}

function updateCursor(e, region) {
  var cursor;
  if (clipSelectionMode)
    cursor = (region==outside)?'default':'crosshair';
  else {
    switch (region) {
      case N: cursor = 'N-Resize'; break;
      case E: cursor = 'E-Resize'; break;
      case S: cursor = 'S-Resize'; break;
      case W: cursor = 'W-Resize'; break;
      case NW: cursor = 'NW-Resize'; break;
      case NE: cursor = 'NE-Resize'; break;
      case SW: cursor = 'SW-Resize'; break;
      case SE: cursor = 'SE-Resize'; break;
      case middle: cursor = 'move'; break;
      default: cursor = 'default';
    }
  }
  _collage.style.cursor = cursor;
}

var last_key_down = -1;
function keyDown(e) {
  if (p == null) return;
  if (!e) e = window.event;
  if (last_key_down == e.keyCode)
    return true;
  last_key_down = e.keyCode;
  switch (e.keyCode) {
    case 83: showExtras = false; redraw(e); return false; //S
  }
  return true;
}
function keyUp(e) {
  if (p == null) return;
  if (!e) e = window.event;
  if (last_key_down == e.keyCode)
    last_key_down = -1;
  switch (e.keyCode) {
    case 83: showExtras = true; redraw(e); return false; //S
    case 88: if (e.ctrlKey) redo(); return false; //X
    case 90: if (e.ctrlKey) undo(); return false; //Z  
  }
  return true;
}
var arrowMoves = 0;
function checkArrowMoves() { if (++arrowMoves > 5) { saveUndo(); arrowMoves = 1; } }
function keyPress(e) {
  if (p == null) return;
  if (!e) e = window.event;
  var elem = getTarget(e);
  var code = e.keyCode==0?e.charCode:e.keyCode;
  switch (code) { //For Safari
    case 63232: code=38; break;  case 63273: code=36; break;
    case 63233: code=40; break;  case 63275: code=35; break;
    case 63234: code=37; break;  case 63276: code=33; break;
    case 63235: code=39; break;  case 63277: code=34; break;
  }
  if (elem.nodeName == 'INPUT' && elem.type == 'text') {
    return ((code >= 48 && code <= 58) || code == 45 || code == 46 || (code >= 37 && code <= 40) || code == 9 || code == 8);
  }
  switch (code) {
    case 37: _x.value = p.pos.x - 1; checkArrowMoves(); redraw(e); break; //left
    case 38: _y.value = p.pos.y - 1; checkArrowMoves(); redraw(e); break; //up
    case 39: _x.value = p.pos.x + 1; checkArrowMoves(); redraw(e); break; //right
    case 40: _y.value = p.pos.y + 1; checkArrowMoves(); redraw(e); break; //down
    case 67: case 99: _clipButton.onclick(); break; //C
    case 76: case 108: _lock.onclick(); break; //L
    case 80: case 112: _center.onclick(); break; //P
    default:
      return true;
  }
  return false;
}
function contextMenu(e) { return false; }
