﻿var tagging = false;
var tagging_initialized = false;
var ajax_done = false;
var friends = null;
var superfriends = null;
var frameWidth = 166;
var frameHeight = 166;
var activePersonID = -2;
var activePersonName ='';
var lastActivePersonName ='';
var activeImageMouseX;
var activeImageMouseY;
var pid = 0;
var id = 0;
var idname = "";
var user = 0;
var oid = 0;
var aid = 0;
var ajax_setter_uri = rootUrl + '/Misc/PhotoAlbum/GetPeopleForPhoto.ashx?requestType=put';
var ajax_getter_uri = rootUrl + '/Misc/PhotoAlbum/GetPeopleForPhoto.ashx?requestType=get';
var ajax_deleter_uri = rootUrl + '/Misc/PhotoAlbum/GetPeopleForPhoto.ashx?requestType=delete';
var ajax_rebuilder_uri = rootUrl + '/Misc/PhotoAlbum/GetPeopleForPhoto.ashx?requestType=rebuild_tags';
var ajax_addTagsButton_uri = rootUrl + '/Misc/PhotoAlbum/GetPeopleForPhoto.ashx?requestType=addTagsButton';
var foundCount = 0;
var lastFoundName = '';
var lastFoundID = 0;
var tagtimerID = 0;
var lastAddedTag = -1;

// minimum W and H of the frame when resizing
var frameMinW = 30, frameMinH = 30;
var frameNewW = 100, frameNewH = 100;

// Helpers and the frame itself
var frameElements;

// Helpers only
var frameHelpers = ['nw', 'n', 'ne', 'w', 'e', 'sw', 's', 'se'];
var frameHelpersCached = new Array();
// cache tagframe width and height
var tfW = 0, tfH = 0, tfX = 0, tfY = 0;

// helpers elements
var h_nw = null, h_n = null, h_he = null, h_w = null, h_e = null, h_sw = null, h_s = null, h_se = null;
// helpers width and height (they're all judged by one 'nw' helper)
var hW = 0; var hH = 0;

// photo area bounding box - don't use in movement calculations!, see below
var paLeft = 0, paRight = 0, paTop = 0, paBottom = 0, paHeight = 0, paWidth = 0;
// same as above, but modified by some little value (currently 0)
// useful if needed to constraint frame movement inside 'photoframe'
// see usage in tagFrameStart
var paLeftH = 0, paRightH = 0, paTopH = 0, paBottomH = 0;		// same as above but minus handlers

// temporary tagframe w, h, l, t
var tW, tH, tX, tY;
// variables to store offset when dragging
var xOff = 0, yOff = 0;
// various values and elements we need to cache
var spy = null, myphoto = null, tf = null, tfi = null, tfi2 = null, tfi3 = null, photoarea = null; 
// faded picture elements
var fPh = null, fT = null, fL = null, fB = null, fR = null;
var myphotoX = 0, myphotoY = 0;

var tfIsShown = false;
var initialized = false;
var currentTagArea = null;
var current_helper = null;

var bigPhotoControlId = '', spyPhotoControlId = '';

function initSrvCtl(bigPhotoId, spyPhotoId)
{
	bigPhotoControlId = bigPhotoId;
	spyPhotoControlId = spyPhotoId;
	frameElements = ['nw', 'n', 'ne', 'w', 'tagframe2', 'tagframe2inside3', spyPhotoId, 'e', 'sw', 's', 'se'];
}

function initElements()
{
	if (!initialized)
	{
		// cache page elements
		h_nw = ge('nw'); 
		h_nw.updatePos = function(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh) {
			h_nw.style.left = justx;
			h_nw.style.top  = justy;
		}
		h_n = ge('n'); 
		h_n.updatePos = function(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh) { 
			h_n.style.left  = plushalfw;
			h_n.style.top   = justy;
		}
		h_ne = ge('ne');
		h_ne.updatePos = function(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh) { 
			h_ne.style.left = pluswholew;
			h_ne.style.top  = justy;
		}
		h_w  = ge('w') ;                
		h_w.updatePos = function(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh) { 
			h_w.style.left  = justx;
			h_w.style.top   = plushalfh;
		}
		h_e  = ge('e') ;
		h_e.updatePos = function(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh) { 
			h_e.style.left  = pluswholew;
			h_e.style.top   = plushalfh;
		}
		h_sw = ge('sw'); 
		h_sw.updatePos = function(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh) { 
			h_sw.style.left = justx;
			h_sw.style.top  = pluswholeh;
		}
		h_s = ge('s'); 
		h_s.updatePos = function(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh) { 
			h_s.style.left  = plushalfw;
			h_s.style.top   = pluswholeh;
		}
		h_se = ge('se');
		h_se.updatePos = function(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh) { 
			h_se.style.left = pluswholew;
			h_se.style.top  = pluswholeh;
		}
		frameHelpersCached = [h_nw, h_n, h_ne, h_w, h_e, h_sw, h_s, h_se];

		myphoto = ge(bigPhotoControlId);
		spy = ge(spyPhotoControlId);
		photoarea = ge('photoarea');
		tf = ge('tagframe2');
		tfi3 = ge('tagframe2inside3');

		// init W and H of helpers (judge by 'nw' helper)
		//hW = parseInt(h_nw.style.width); hH = parseInt(h_nw.style.height);
		// HACK! Need to read it from stylesheets, but how?
		hW = 10; hH = 10;

		for (var coord in tag_coords)
		{
			var x1 = tag_coords[coord][0] * myphoto.width / 100;
			var y1 = tag_coords[coord][1] * myphoto.height / 100;
			var x2 = tag_coords[coord][2] * myphoto.width / 100;
			var y2 = tag_coords[coord][3] * myphoto.height / 100;

			if (!x2)
			{
				x1 -= 83;
				x2 = x1 + 166;
			}

			if (!y2)
			{
				y1 -= 83;
				y2 = y1 + 166;
			}
	
			with(Math)
			{
				tag_coords[coord][0] = round(x1);
				tag_coords[coord][1] = round(y1);
				tag_coords[coord][2] = round(x2);
				tag_coords[coord][3] = round(y2);
			}
		}
	}

	photoarea.style.width = myphoto.width + "px";
	photoarea.style.height = myphoto.height + "px";

	// cache and init values of faded elements that won't change
	fPh = $('fadedphoto');

	myphotoX = findX(myphoto);
	myphotoY = findY(myphoto);

	// You can change values with 'H' suffix to apply contraints on frame movement
	paLeft = findX(photoarea) + 1;
	paLeftH = paLeft;
	paTop = findY(photoarea); paTopH = paTop;
	
	paWidth = photoarea.clientWidth;
	paHeight = photoarea.clientHeight;
	
	paRight = paLeft + paWidth; 	paRightH = paRight;
	paBottom = paTop + paHeight; 	paBottomH = paBottom;

	fPh.style.left = "0px";
	fPh.style.top = "0px";
	fPh.style.width = myphoto.width + "px";
	fPh.style.height = myphoto.height + "px";
	
	selectorHelp();
	
	initialized = true;
}

function showBoxAt(x1, y1, x2, y2, norecount)
{
	if (tfIsShown)
		return;

	initElements();

	if (norecount == null || !norecount)
	{
		tfX = x1 * myphoto.width / 100;
		tfY = y1 * myphoto.height / 100;

		if (!x2)
		{
			tfW = 166;
			tfX -= 83;
		}
		else	
			tfW = x2 * myphoto.width / 100.0 - x1 * myphoto.width / 100.0;
		if (!y2)
		{
			tfH = 166;
			tfY -= 83;
		}
		else	
			tfH = y2 * myphoto.height / 100.0 - y1 * myphoto.height / 100.0;
	}
	else
	{
		tfX = x1;
		tfY = y1;
		tfW = x2 - x1;
		tfH = y2 - y1;
	}

	updateFramePos(Math.round(tfX), Math.round(tfY));
	updateFrameSize(Math.round(tfW), Math.round(tfH));
	updateFaded();
	
	show('tagframe2');
	show('tagframe2inside3');
	show('fadedphoto');
}

function hideBox()
{
	if (tfIsShown)
		return;

	hide('tagframe2');
	hide('tagframe2inside3');
	hide('fadedphoto');
	hide('nw'); hide('n'); hide('ne');
	hide('w'); hide('e');
	hide('sw'); hide('s'); hide('se');
}

//set the tagsBar in the progress state
function tagsBarProgress()
{
	ge("phototags").innerHTML = "";
}

function removeTag(tagId, photoId, uid)
{
	tagsBarProgress();
	
  var ajax = new PhotoAlbumAjax();

  ajax.onDone = function (ajaxObj, responseText) {
      hideBox();
      var arr = responseText.split("!");
      ge("phototags").innerHTML = arr[1];
      build_friends_list(photoId, uid, '', uid, 0, 0);
  }
 
  ajax.onFail = function (ajaxObj) {}
  
	for (i = 0; i < tag_coords.length; i++)
	{
		if (tag_coords[i][6] == tagId)
		{
			tag_coords.splice(i, 1);
		}
	}
 
  ajax.post(ajax_deleter_uri, 'tag_id=' + tagId + '&pid=' + photoId);
  return false;
}

function rebuildTags(photo_id, user_id)
{
	tagsBarProgress();
	
    var ajax = new PhotoAlbumAjax();

    ajax.onDone = function (ajaxObj, responseText) 
    {
        var arr = responseText.split("!");
		ge("phototags").innerHTML = arr[1];
        
        eval(arr[2]);
        
        //инициализируем все элементы заново
        initialized = false;
        initElements();
        
        //setting the tagbar size
		setupTagbarSize();
				
			if (document.getElementById('phototags').innerHTML == '')
			{
				document.getElementById('phototags').style.display='none';
			}
			else
				document.getElementById('phototags').style.display='';

    }

    ajax.onFail = function () {}

    params = 'pid=' + photo_id + '&id='  + id;

    ajax.post(ajax_rebuilder_uri, params);
}

function rebuildAddTagsButton(photo_id)
{
    var ajax = new PhotoAlbumAjax();

    ajax.onDone = onAddTagsButton;

    ajax.onFail = function () {}

    params = 'pid=' + photo_id;
    ajax.post(ajax_addTagsButton_uri, params);
}

function onAddTagsButton(ajaxObj, responseText)
{
    var arr = responseText.split("!");
    
    if(arr[0] != "")
    {
        ge("addtagsbutton").innerHTML = arr[0];
        ge("addtagsbutton").style.display = "block";
        
    }
    else
    {
        ge("addtagsbutton").innerHTML = "";
        ge("addtagsbutton").style.display = "none";
    }
}

function submitTag() {
	
	tagsBarProgress();
	
  var ajax = new PhotoAlbumAjax();

  ajax.onDone = function (ajaxObj, responseText) {
    var arr = responseText.split("!");
	tag_coords[lastAddedTag][6] = arr[0];
    ge("phototags").innerHTML = arr[1];

    //indicate success to the user
    var successName;
    var requestText;
    var successMessage = "";
    if (id == user) {
        requestText = " ";
        tagAction = " tag ";
    } else {
        requestText = " request ";
        tagAction = " request tags in ";
    }
    if (activePersonName == 'Я') {

     successMessage = 
       '<b>Вы сохранены на этой фотографии';

        successName = "Вы";
    } else {
        if (!activePersonName) {
            //sometimes ajax is slow so we use what's in lastActivePersonName
            //b/c we may have overridden the old activePersonName b/c of
            //asynchronous ajax call
            successName = lastActivePersonName; 
        } else {
            successName = activePersonName; 
        }

    successMessage = 
      '<b>Пользователь ' + successName;
      successMessage += ' был сохранён на этой фотографии';
    }

    successMessage += '</b>.';

    successMessage += '<br />Когда закончите отмечать друзей, нажмите кнопку "Готово".';
  
    hide('tagging_instructions_default_message');
    ge('tagging_instructions_status_message').innerHTML = successMessage;
		show('tagging_instructions_status_message');
  	hide("selector_progressbar");
	show("selector_buttons");  	
    resetSelector();
    focusInstructions();
    return false;
  }
  
  ajax.onFail = function (ajaxObj) {
  	hide("selector_progressbar");
	show("selector_buttons");  	
  }

  percentX_topleft = tfX / myphoto.width * 100;
  percentY_topleft = tfY / myphoto.height * 100;
  percentX_bottomright = (tfX + tfW) / myphoto.width * 100;
  percentY_bottomright = (tfY + tfH) / myphoto.height * 100;
	frameNewW = tfW;
	frameNewH = tfH;

	tag_coords.push(new Array(tfX, tfY, tfX + tfW, tfY + tfH, activePersonID, activePersonName));
	lastAddedTag = tag_coords.length - 1;
	
  // var personEmail = ge('invite_email').value;

	params = 'pid=' + pid
				+ '&id='  + id 
				+ '&oid=' + oid  
				+ '&subject=' + activePersonID
				+ '&name=' + encodeURI(activePersonName)
				// + '&email=' + personEmail 
				+ '&add=1'
				+ '&x=' + percentX_topleft
				+ '&y=' + percentY_topleft
				+ '&x2=' + percentX_bottomright
				+ '&y2=' + percentY_bottomright;

	show("selector_progressbar");
	hide("selector_buttons");  	
  
  ajax.post(ajax_setter_uri, params);

  //remove that id from the tagging list 
  removeTagOption(activePersonName, activePersonID);
}

function removeTagOption(removeName, removeID) {
    superfriends = removeFromList(removeName, removeID, superfriends);
    friends = removeFromList(removeName, removeID, friends);
}

function removeFromList(removeName, removeID, list) {
    listCount = list.length;
  for (i = 0; i < listCount; i++) {
      if( list[i]['name'] == removeName && 
          list[i]['id'] == removeID
        ) {
          list.splice(i, 1);
          break;
      }
  }

  return list;
}

function resetTeggingEnvironment()
{
    initialized = false;
    initElements();
    
    tagging_initialized = false;
    hide_tagging_ui();
}

function build_friends_list(photo_id, owner_id, owner_name,
                         user_id, album_id, obj_id) {
   
    pid = photo_id;
    id = owner_id;
    user = user_id;
    aid = album_id;
    oid = obj_id;
    idname = unescapeQuotes(owner_name);

    tagging = true;

    //get them ajax style
    var ajax = new PhotoAlbumAjax(onGetTagOptionsSuccessFn, onGetTagOptionsFailFn);
    ajax.get(ajax_getter_uri + 
            '&id='+user+'&pid='+pid+'&aid='+aid+'&oid='+oid);
    tagging_initialized = true;
    registerKeys();
}

function show_tagging_ui(photo_id, owner_id, owner_name, 
                         user_id, album_id, obj_id) {
                   
    pid = photo_id;
    id = owner_id;
    user = user_id;
    aid = album_id;
    oid = obj_id;
    idname = unescapeQuotes(owner_name);

    tagging = true;
    if (!tagging_initialized) {
        //get them ajax style
        var ajax = new PhotoAlbumAjax(onGetTagOptionsSuccessFn, onGetTagOptionsFailFn);
        ajax.get(ajax_getter_uri + 
                '&id='+user+'&pid='+pid+'&aid='+aid+'&oid='+oid);
        tagging_initialized = true;
        registerKeys();
    }
    
    ge('name').value='';
    ge(bigPhotoControlId).style.cursor = 'crosshair';
    tagFrameStart();
}

function focusInstructions() {
    /* window.location.hash = 'tagging_instructions'; */
}

function hide_tagging_ui() {
    tagging = false;

    tagFrameFinish();
    ge(bigPhotoControlId).style.cursor = '';
    hide('tagging_instructions_status_message');
    hide('tagging_instructions_default_message');
    hide('tagging_instructions');	

    //hide these, they may be showing
    hide('selector');
}

function onGetTagOptionsSuccessFn(ajaxObj, responseText) {
    //take out the people who are tagged already- wish list
    //show super of "Me" ( wish list - if you are not already tagged )
    eval(responseText);
    if(!friends_ajax)
    {
        friends_ajax = [];
    }
    
    friends = friends_ajax;
    superfriends = superfriends_ajax;
    populateSelector();
    ajax_done = true;
}

function tagHit() {
    if ((activePersonID == -2 || activePersonName == "") && 
            ge('name').value == "") {
        return false;
    }
    if (activePersonID == -2) {
        activePersonName = ge('name').value; //text tagging
        if (activePersonName.toLowerCase() == 'me') {
            activePersonID = user; 
        } else {
            activePersonID = 0; //don't need neg flags here
        }
    }

    lastActivePersonName = activePersonName;
    
    submitTag();
    
	return false;
}

function resetSelector() {
  hide('selector');  
  activePersonID = -2;
  activePersonName = "";
  ge('name').value = "";  
  //ge('invite_email').value='';
  populateSelector();

	tfIsShown = false;
	hideBox();
}

function populateSelector() {
    var i = 0;
    var filter = ge('name').value.toLowerCase();
    var filterLen = filter.length;
    var superContents = "";
    var friendContents = "";
    var sepContents = "";
    var superCount = 0;

    if (filter == "") {
        filter = null;
    }
    
    foundCount = 0;

    superContents = render_userlist(superfriends, filter);
    superCount = foundCount;

    // Maybe add a Divider

    friendContents = render_userlist(friends, filter);
    
    // If only one, we don't need divider
    if (superCount > 0 && foundCount > 1) {
        sepContents = "<hr />";
    }

    ge('userlist').innerHTML = superContents + sepContents + friendContents;

    if (foundCount == 1) {
        activePersonID = lastFoundID;
        activePersonName = unescapeQuotes(lastFoundName);
        ge('f0').checked = true; //check it
    }


    // hide('invite_section');
    // If no user is Chosen, might hide userlist
    if(foundCount == 0) {
        hide('userlist');
        hide('userlistlabel');

        // currently we don't support email invites to tuna objects
        if(filter && id == user && !oid)
        {
          maybe_show_invite_section(filter);
        }
    } else {
        show('userlist');
        show('userlistlabel');
    }
}

function render_userlist(list, filter) {
    var listCount = list.length;
    var str = "";
    for (i = 0; i < listCount; i++) {
       
        if(!filter || list[i]['name'].toLowerCase().indexOf(filter) != -1 ) {str += "<input style='width: auto;' type=checkbox onclick=\"pHit(this); hide_tagging_ui();\" name='f"+foundCount+"' id='f"+foundCount+"' friend=\"" + list[i]['name'] + "\" value=" + list[i]['id'] + "><label style='display: inline;' for='f"+foundCount+"'>" + unescapeQuotes(list[i]['name']) + "</label><br>";
            lastFoundName = decodeURI(list[i]['name']);
            lastFoundID = list[i]['id'];
            foundCount++;
        }
    }
    return str;
}

function onGetTagOptionsFailFn() {
}

function imageMouseUp() {
    if (tagging) {
        ge('name').focus();
        ge('name').select();
    }
}

function showBoxOnMove(e)
{
	initElements();

	var x = mousePosX(e);
	var y = mousePosY(e);
	var gotit = false;

	if (currentTagArea != null &&
			x >= paLeft + currentTagArea[0] && y >= paTop + currentTagArea[1] &&
			x <= paLeft + currentTagArea[2] && y <= paTop + currentTagArea[3])
	{
		return cancelEvent(e);
	}

	for(var c in tag_coords)
	{
			if (x >= paLeft + tag_coords[c][0] && y >= paTop + tag_coords[c][1] &&
					x <= paLeft + tag_coords[c][2] && y <= paTop + tag_coords[c][3])
			{
				params = new Array(tag_coords[c][0], tag_coords[c][1], tag_coords[c][2], tag_coords[c][3], 1);
				params = params.join(", ");
				clearTimeout(tagtimerID);
				tagtimerID = 0;
				var tagname = ge('tagname');
				if (tag_coords[c][4])
					tagname.innerHTML = "<a href='" + rootUrl + "/ViewUser.aspx?ID=" + tag_coords[c][4] + "'>" + tag_coords[c][5] + "</a>";
				else
					tagname.innerHTML = tag_coords[c][5];
				tagname.style.left = tag_coords[c][0] + "px";
				tagname.style.top = tag_coords[c][3] + "px";
				tagname.style.width = tag_coords[c][2] - tag_coords[c][0] + "px";
				show('tagname');
				if (tag_coords[c][3] + tagname.clientHeight > paHeight) {
					tagname.style.top = tag_coords[c][3] - tagname.clientHeight + "px";
				}
				if (tag_coords[c][0] + tagname.clientWidth > paWidth) {
					tagname.style.left = paWidth - tagname.clientWidth - 2 + "px";
				}
				gotit = true;
				currentTagArea = tag_coords[c];
				break;
			}
	}

	if (!gotit)
	{
		if (!tagtimerID)
			tagtimerID = setTimeout(function(){hide('tagname')}, 50);
		currentTagArea = null;
	}

	return cancelEvent(e);
}

function tagFrameStart()
{
	initElements();

	removeEvent(photoarea, "mousemove");
	removeEvent(tfi3, 'mousemove');
	removeEvent(spy, 'mousemove');
	addEvent(photoarea, 'mousedown', createFrame);
	ge('myphotolink').onclick = "return false;";
	//addEvent(ge('myphotoup'), 'mouseup', function (e) { cancelEvent(e); })
	for (i = 0; i < frameElements.length; i++)
	{
		addEvent(ge(frameElements[i]), 'mousedown', frameMouseDown);
		addEvent(ge(frameElements[i]), 'mouseup', frameMouseUp);
	}
	
	tagging = true;

}

function showTeggingEnvironment()
{
	x = 0;
	y = 0;

	for (i = 0; i < frameElements.length; i++)
		show(frameElements[i]);

	show('fadedphoto');
	show('selector');

	updateFrameSize(frameNewW, frameNewH);
	updateFramePos(x - frameNewW / 2 - paLeft, y - frameNewH / 2 - paTop);
	updateSelector();
	updateFaded();
	var justx = tfX + 1 + "px";
	var justy = tfY + 1 + "px";
	var plushalfw  = tfX + (tfW / 2) - (hW / 2) + 1 + "px";
	var pluswholew = tfX + tfW - hW + 1 + "px";
	var plushalfh  = tfY + (tfH / 2) - (hH / 2) + 1 + "px";
	var pluswholeh = tfY + tfH - hH + 1 + "px";
	for (i = 0; i < frameHelpersCached.length; i++)
		frameHelpersCached[i].updatePos(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh);

	tfIsShown = true;
}

function tagFrameFinish()
{
	mouseUp();
	removeEvent(photoarea, 'mousedown');
	ge('myphotolink').onclick = "";
	//removeEvent(ge('myphoto'), 'mouseup');
	for (i = 0; i < frameElements.length; i++)
	{
		removeEvent(ge(frameElements[i]), 'mousedown');
		removeEvent(ge(frameElements[i]), 'mouseup');
	}
	addEvent(tfi3, "mousemove", function(e) { return cancelEvent(e); });
	addEvent(spy, "mousemove", function(e) { return cancelEvent(e); });
	addEvent(photoarea, "mousemove", showBoxOnMove);

	tfIsShown = false;	
	tagging = false;
	
	hideBox();

	//ge('myphotolink').href = href;
}


function createFrame(e)
{
	x = mousePosX(e);
	y = mousePosY(e);

	for (i = 0; i < frameElements.length; i++)
		show(frameElements[i]);

	show('fadedphoto');
	show('selector');

	updateFrameSize(frameNewW, frameNewH);
	updateFramePos(x - frameNewW / 2 - paLeft, y - frameNewH / 2 - paTop);
	updateSelector();
	updateFaded();
	var justx = tfX + 1 + "px";
	var justy = tfY + 1 + "px";
	var plushalfw  = tfX + (tfW / 2) - (hW / 2) + 1 + "px";
	var pluswholew = tfX + tfW - hW + 1 + "px";
	var plushalfh  = tfY + (tfH / 2) - (hH / 2) + 1 + "px";
	var pluswholeh = tfY + tfH - hH + 1 + "px";
	for (i = 0; i < frameHelpersCached.length; i++)
		frameHelpersCached[i].updatePos(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh);

	tfIsShown = true;

	return cancelEvent(e);
}

function updateFrameSize(W, H)
{
	if (W >= 0)
	{
		tfW = W;
		tf.style.width = W - 10 + "px";
		tfi3.style.width = W - 12 + "px";
	}

	if (H >= 0)
	{		
		tfH = H;
		tf.style.height = H - 10 + "px";
		tfi3.style.height = H - 12 + "px";
	}
}

function updateFramePos(x, y)
{
	// Apply constraints
	if (x < 0)
		x = 0;
	if (x + tfW + 2> paWidth)
		x = paWidth - tfW - 2;
	if (y < 0)
		y = 0;
	if (y + tfH + 2 > paHeight)
		y = paHeight - tfH - 2;

	tfX = x; tfY = y;

	tf.style.left = tfX + "px";
	tf.style.top = tfY + "px";

	var justx = tfX + 1 + "px";
	var justy = tfY + 1 + "px";
	var plushalfw  = tfX + (tfW / 2) - (hW / 2) + 1 + "px";
	var pluswholew = tfX + tfW - hW + 1 + "px";
	var plushalfh  = tfY + (tfH / 2) - (hH / 2) + 1 + "px";
	var pluswholeh = tfY + tfH - hH + 1 + "px";
	
	if (null != current_helper) {
		current_helper.updatePos(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh);
	} 
}

function updateFaded()
{
	spy.style.left = -tfX - 8 + "px";
	spy.style.top = -tfY - 8 + "px";
}

function updateSelector()
{
	var sel = ge('selector');
	sel.style.top  = paTop + tfY + "px";
	if (tfX + tfW + 20 + sel.clientWidth < paWidth + 113) {
		sel.style.left = paLeft + tfX + tfW + 20 + "px";		
	} else {
		sel.style.left = paLeft + tfX - 20 - sel.clientWidth + "px";		
	}		
}

function frameMouseDown(e)
{	
	// Save values at the beginning of resize
	tX = tfX; tY = tfY;
	tW = tfW; tH = tfH;

	target = (e.srcElement) ? e.srcElement : e.target;
	targetid = target.id == '' ? target.parentNode.id : target.id;

	hide('selector');
	addEvent(document.body, 'mouseup', frameMouseUp);	
	addEvent(document.body, 'dragend', frameMouseUp);

	// There is a less painful way to do this, but there are more on-move calculations. Anyway, fuck it. Does its job.
		switch(targetid)
		{
			case 'tagframe2':
			case 'tagframe2inside3':
				hideHelpers();
				selectorControls();
				photoarea.style.cursor = 'move';
				xOff = tfX - mousePosX(e);
				yOff = tfY - mousePosY(e);
				assignMove(frameMove);
				break;
			case 'nw':
				hideHelpers(targetid);
			selectorControls();
				current_helper = h_nw;
				xOff = tfX + paLeft - mousePosX(e);
				yOff = tfY + paTop - mousePosY(e);
				tf.style.cursor = photoarea.style.cursor = 'nw-resize';
				assignMove(function (e) {
					x = Math.min(tfX + tfW - frameMinW, Math.max(0, mousePosX(e) - paLeft + xOff));
					y = Math.min(tfY + tfH - frameMinH, Math.max(0, mousePosY(e) - paTop + yOff));
					updateFrameSize(tW + tX - x, tH + tY - y);	
					updateFramePos(x, y);
					updateFaded();
					return cancelEvent(e); 		

				} );
				break;
			case 'n':
				hideHelpers(targetid);
			selectorControls();
				current_helper = h_n;
				yOff = tfY + paTop - mousePosY(e);
				tf.style.cursor = photoarea.style.cursor = 'n-resize';
				assignMove(function (e) {
					y = Math.min(tfY + tfH - frameMinH, Math.max(0, mousePosY(e) - paTop + yOff));
					updateFrameSize(-1, tH + tY - y);	
					updateFramePos(tfX, y); 		
					updateFaded();
					return cancelEvent(e); 		
				} );
				break;
			case 'ne':
				hideHelpers(targetid);
			selectorControls();
				current_helper = h_ne;
				xOff = tfX + paLeft + tfW - mousePosX(e);
				yOff = tfY + paTop - mousePosY(e);
				tf.style.cursor = photoarea.style.cursor = 'ne-resize';
				assignMove(function (e) {
					x = Math.min(paWidth - 2, Math.max(tfX + frameMinW, mousePosX(e) - paLeft + xOff));
					y = Math.min(tfY + tfH - frameMinH, Math.max(0, mousePosY(e) - paTop + yOff));
					updateFrameSize(x - tX, tH + (tY) - y);	
					updateFramePos(tX, y); 		
					updateFaded();
					return cancelEvent(e); 		
				} );
				break;
			case 'w':
				hideHelpers(targetid);
			selectorControls();
				current_helper = h_w;
				xOff = tfX + paLeft - mousePosX(e);
				tf.style.cursor = photoarea.style.cursor = 'w-resize';
				assignMove(function (e) {
					x = Math.min(tfX + tfW - frameMinW, Math.max(0, mousePosX(e) - paLeft + xOff));
					updateFrameSize(tW + tX - x, -1);	
					updateFramePos(x, tfY); 		
					updateFaded();
					return cancelEvent(e); 		
				} );
				break;
			case 'e':
				hideHelpers(targetid);
			selectorControls();
				current_helper = h_e;
				tf.style.cursor = photoarea.style.cursor = 'e-resize';
				xOff = tfX + paLeft + tfW - mousePosX(e);
				assignMove(function (e) {
					x = Math.min(paWidth - 2, Math.max(tfX + frameMinW, mousePosX(e) - paLeft + xOff));
					updateFrameSize(x - tX, -1);	
					updateFramePos(tfX, tfY); 		
					updateFaded();
					return cancelEvent(e); 		
				} );
				break;
			case 'sw':
				hideHelpers(targetid);
			selectorControls();
				current_helper = h_sw;
				tf.style.cursor = photoarea.style.cursor = 'sw-resize';
				xOff = tfX + paLeft - mousePosX(e);
				yOff = tfY + paTop + tfH - mousePosY(e);
				assignMove(function (e) {
					x = Math.min(tfX + tfW - frameMinW, Math.max(0, mousePosX(e) - paLeft + xOff));
					y = Math.min(paHeight - 2, Math.max(tfY + frameMinH, mousePosY(e) - paTop + yOff));
					updateFrameSize(tX - x + tW, y - tY);	
					updateFramePos(x, tY); 		
					updateFaded();
					return cancelEvent(e); 		
				} );
				break;
			case 's':
				hideHelpers(targetid);
			selectorControls();
				current_helper = h_s;
				tf.style.cursor = photoarea.style.cursor = 's-resize';
				yOff = tfY + paTop + tfH - mousePosY(e);
				assignMove(function (e) {
					y = Math.min(paHeight - 2, Math.max(tfY + frameMinH, mousePosY(e) - paTop + yOff));
					updateFrameSize(-1, y - tY);	
					updateFramePos(tX, tY); 		
					updateFaded();
					return cancelEvent(e); 		
				} );
				break;
			case 'se':
				hideHelpers(targetid);
			selectorControls();
				current_helper = h_se;
				tf.style.cursor = photoarea.style.cursor = 'se-resize';
				xOff = tfX + paLeft + tfW - mousePosX(e);
				yOff = tfY + paTop + tfH - mousePosY(e);
				assignMove(function (e) {
					x = Math.min(paWidth - 2, Math.max(tfX + frameMinW, mousePosX(e) - paLeft + xOff));
					y = Math.min(paHeight - 2, Math.max(tfY + frameMinH, mousePosY(e) - paTop + yOff));
					updateFrameSize(x - tX, y - tY);	
					updateFramePos(tX, tY); 		
					updateFaded();
					return cancelEvent(e); 		
				} );
				break;
				
			default:
				break;			
		}
	
	if(targetid == spyPhotoControlId)
	{
			hideHelpers();
			selectorControls();
			photoarea.style.cursor = 'move';
			xOff = tfX - mousePosX(e);
			yOff = tfY - mousePosY(e);
			assignMove(frameMove);
	}

	return cancelEvent(e);
}

function hideHelpers(keep) {
	for (i = 0; i < frameHelpers.length; i++)
		if (frameHelpers[i] != keep)
			hide(frameHelpers[i]);
}

function showHelpers() {	
	for (i = 0; i < frameHelpers.length; i++)
		show(frameHelpers[i]);
	current_helper = null;
}

function frameMouseUp(e)
{
	mouseUp();

	return cancelEvent(e);
}

var frameMove = function(e)
{
	x = mousePosX(e);
	y = mousePosY(e);
	updateFramePos(x + xOff, y + yOff);		
	updateFaded();

	return cancelEvent(e);
}

function mouseUp()
{
	removeEvent(document.body, 'mouseup');
	removeEvent(document.body, 'dragend');
	assignMove('');
	showHelpers();
	var justx = tfX + 1 + "px";
	var justy = tfY + 1 + "px";
	var plushalfw  = tfX + (tfW / 2) - (hW / 2) + 1 + "px";
	var pluswholew = tfX + tfW - hW + 1 + "px";
	var plushalfh  = tfY + (tfH / 2) - (hH / 2) + 1 + "px";
	var pluswholeh = tfY + tfH - hH + 1 + "px";
	for (i = 0; i < frameHelpersCached.length; i++)
		frameHelpersCached[i].updatePos(justx, justy, plushalfw, pluswholew, plushalfh, pluswholeh);
	show('selector');
	updateSelector();
	tf.style.cursor = photoarea.style.cursor = '';
}

function assignMove(func)
{
	if (func != '')
	{
		addEvent(document.body, 'mousemove', func );
		addEvent(document.body, 'drag', func );
	}
	else	
	{
		removeEvent(document.body, 'mousemove');
		removeEvent(document.body, 'drag');
	}
}

function addEvent(obj, event, handler) 
{
	var fn = handler;

	if (!obj.attachedEvents)
		obj.attachedEvents = new Array();

	if (obj.attachedEvents[event])
		removeEvent(obj, event);

	obj.attachedEvents[event] = fn;

	if (typeof obj.addEventListener != 'undefined') 
		obj.addEventListener(event, handler, false);
	else if (typeof obj.attachEvent != 'undefined') 
		obj.attachEvent('on' + event, handler);
}

function removeEvent(obj, event)
{
	if (!obj.attachedEvents || !obj.attachedEvents[event])
		return;

	if (typeof obj.removeEventListener != 'undefined') 
		obj.removeEventListener(event, obj.attachedEvents[event], false);
	else if (typeof obj.detachEvent != 'undefined') 
		obj.detachEvent('on' + event, obj.attachedEvents[event]);
}      


function cancelEvent(e) 
{
	var e = e ? e : window.event;
		
	if(e.preventDefault)
		e.preventDefault();

	if(e.stopPropagation) 
		e.stopPropagation(); 

	e.cancelBubble = true;

	// butter buttered =)
	e.returnValue = false;
	return false;
}

function selectorControls()
{
	show('selectorControls');
	hide('selectorHelp');
}

function selectorHelp()
{
	hide('selectorControls');
	show('selectorHelp');
}

