var search_req;
var search_timeout_id;
var signup_time;

// Set at nav to curio
var curio_id     = "";
var curio_height = 0;
var curio_width  = 0;
var curio_name   = "";
var curio_desc   = "";
var mouse_inside = false;
var first_time   = true;

var num_fields   = 0;
var pagination   = 0;
var page_loading = false;
var last_searched= null;

var MODE_CREATE  = 0;
var MODE_PRES    = 1;
var MODE_ADD     = 2;
var MODE_EDIT    = 3;
var MODE_INSTANCE= 4;

var NUM_PAGE = 50;

var change_counter = 0;
var curio_changing = false;

var img_arr = [];
var img_counter = 0;
var DEFAULT_IMG = '/images/default.gif';
var DEFAULT_TITLE = "Title";
var DEFAULT_DESC  = "Description";

// Defined in 'formats' table, also used in actions/curio_create.php
var ELEM_TYPE = {
	LINK		   : 0,
	TEXT_FORMATTED : 1,
	TEXT		   : 2,
	STRING         : 3,
	DATE           : 4,
	INT            : 5,
	LIST           : 6,
	IMAGE          : 7,
	FLOAT		   : 8
};

var filler = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor" + 
			 "incididunt ut labore et dolore magna aliqua."

$(document).ready(function(e) {
	function loadImages() {
		def_imag = new Image(); 
		def_imag.src = DEFAULT_IMG;
	}
	loadImages();

	$('#loading').show();

	$('body').on('mousedown', click_body);

	//var History = window.History;
    //if ( !History.enabled ) {
    //    return false;
    //}

	// StateChange Event
    //History.Adapter.bind(window,'statechange',function() {
        //var state = History.getState();
    (function process_url() {
        var array_components = window.location.href.replace('//','').split('\/');

        // get query or instance_id if it's there
        var q   = $.bbq.getState('q') || '';
        var iid = $.bbq.getState('iid') || '';

        if( curio_name == unfix_title(array_components[1] ))
        	return true;

       	// Clear the state
       	nav_to_curio(null);

       	var c = '';
       	var uid = '-1';
       	// curio.org / coffee / q=a
       	if( array_components.length == 3) {
       		c = array_components[1];

       	// curio.org / 123 / coffee / q=a
       	} else if (array_components.length == 4 ) {
       		uid = array_components[1];
       		c = array_components[2];
       	}

       	if( curio_name == '' || $('#current_curio').css('display') == 'none' ) {
        	if( c.indexOf('#') == -1 ) {
        		nav_to_curio(unfix_title(c), uid);
        	} else {
        		nav_to_curio(unfix_title(c.slice(0,c.indexOf('#'))), uid);
        	}
       	}

        var state = {}
        if( q != '' ) {
        	$.bbq.removeState('q');
        	state['q'] = q;
        }

        if( iid != '' ) {
        	$.bbq.removeState('iid');
        	state['iid'] = iid;
        }

        if( iid != '' || q != '' ) {
        	$.bbq.pushState( state );
        }

        $('#search').val('');
        return false;
    })();
    //$(window).trigger('statechange');

	$('.default_value').each(function() {
	    var default_value = this.value;
	    $(this).toggleClass('default_val');
	    
	    $(this).focus(function() {
	        if(this.value == default_value) {
	            this.value = '';
				$(this).toggleClass('default_val');
	        } 
	
	    });
	    $(this).blur(function() {
	        if(this.value == '') {
	            this.value = default_value;
				$(this).toggleClass('default_val');
	        }
	    });
	});
	
	// Set focus on search bar, wait for IE to catch up
	setTimeout(function() { $('#search').focus() }, 150);
	
	function make_layout_resizable(layout) { 
		layout.css('border', '1px solid #D6D6D6');
		layout.resizable({
			autoHide: true,
			resize: function() {
				var newMinHeight = 150;
				var newMinWidth = 500;
				$('#curio_layout div.cl').each(function(i) {
					var x = $(this).position().left + $(this).width();
					var y = $(this).position().top + $(this).height();

					if( x > newMinWidth )
						newMinWidth = x;
					if( y > newMinHeight )
						newMinHeight = y;
				})

				$(this).resizable({ minWidth:newMinWidth, minHeight:newMinHeight  });
			},
	        alsoResize: $('#main_window'),
			grid:5
		});
	}

	$('#create_new').on('click', function() {
		var form = $('#create_form');

		$.ajax({
			type: 'POST',
			url:  form.attr('action'),
			data: form.serialize(),
			success: function(data) {
				switch (parseInt($('#FORM_MODE').attr('value'))) {
					case MODE_EDIT:
					case MODE_CREATE:
						var json = $.parseJSON(data);
			
						if( json.code == 0 ) {
							//nav_to_curio(unfix_title($('#curio_title').val()), getUID());
							//detachLayoutItems();
							window.location = json.msg;
						} else {
							show_and_set_error($('#window_error_message'), json.msg);	
						}
						break
					default:
						window.location.reload();
						$(window).trigger('statechange');
						break;
				}	
			}
		});
	});

	$('#newcurio').on('click', function() {
		// Set mode to create
		$('#FORM_MODE').attr('value', MODE_CREATE);
		$('.white_content').css('position','fixed');
		
		$('#main_window_title').html('create new curio');
		var curio_layout = $('#curio_layout');
		curio_layout.css('height', '220px');
		curio_layout.css('width', '650px');
		curio_layout.resizable('destroy');
		
		$('#create_new').show();
		$('#create_new').val('create');
		$('#close_main_window').show();

		$('#curio_access_public').click();
		
		var main_window = $('#main_window');

		main_window.css('height','auto');
		main_window.css('width', 'auto');

		make_layout_resizable(curio_layout);
	
		$('#curio_title').val(DEFAULT_TITLE).addClass('default_val');
		$('#curio_desc').val(DEFAULT_DESC).addClass('default_val');
		$('#create_curio_components').css('display', 'inline');
		show_main_window(true);
	});

	$('#editcurio').on('click', function() {
		var window_content = $('#main_window');
		$('#main_window_title').html('edit curio');
		window_content.css('height', 'auto');
		window_content.css('width', 'auto');

		$('#FORM_MODE').attr('value', MODE_EDIT);
		$('#create_new').show();
		$('#close_main_window').show();

		// Get the cid and then retrieve the layout
		var curio = curio_id || '';
		$('#cid').attr('value', curio);

		$.ajax({
			type: 'GET',
			url:  '/actions/grab.php',
			data: {q:'getcuriolayout', p1:curio},
			success: function(data) {
				var curio_layout = $('#curio_layout');
				curio_layout.show();

				var json = $.parseJSON(data);
				make_layout_resizable(curio_layout);
				processLayout(json, MODE_EDIT);

				$('#curio_title').val(curio_name).removeClass('default_val');
				$('#curio_desc').val(curio_desc).removeClass('default_val');
				$('#create_curio_components').css('display', 'inline');
				$('#create_new').val('save');

				if( json.length > 0 && json[0].private && json[0].private == "1" )
					$('#curio_access_private').click()
				else
					$('#curio_access_public').click();

				show_main_window(true);
				return true;
			}
		});
	});
	
	$('#addentry').on('click', function() {
		var window_content = $('#main_window');
		$('#main_window_title').html('add entry');
		window_content.css('height', 'auto');
		window_content.css('width', 'auto');
		
		var curio_layout = $('#curio_layout');
		curio_layout.show();
		curio_layout.css('border', '1px solid #D6D6D6');
		curio_layout.resizable('destroy');
		$('#close_main_window').show();
		$('#window_error_message').hide();

		// hide create stuff
		$('#create_curio_components').hide();
		
		$('#FORM_MODE').attr('value', MODE_ADD);
		$('#create_new').show();
		$('#create_new').val('create');
		
		// Get the cid and then retrieve the layout
		var curio = curio_id || '';
		$('#cid').attr('value', curio);
		
		$.ajax({
			type: 'GET',
			url:  '/actions/grab.php',
			data: {q:'getcuriolayout', p1:curio},
			success: function(data) {
				processLayout($.parseJSON(data), MODE_ADD);
				show_main_window(true);
				return true;
			}
		});
	});
	
	$('#login_form').on('click', function(event) {
		event.stopPropagation();
	});

	$('#login_form').on('keyup', function(event) {
		var code = (event.keyCode ? event.keyCode : event.which);
		if(code == 13) {
			if( $('#signup_components').css('display') == 'block' ) {
				$('#signup_btn').trigger('click');
			} else {
				$('#login_btn').trigger('click');
			}
		}
	});

	$('#login').on('click', function(event) {
		$('#login').removeClass('pressed');
		$('#signup').removeClass('pressed');

		var login_form = $('#login_form');
		
		// login specifics
		login_form.css('right', '0px');
		login_form.css('height', '105px');
		$('#signup_components').hide();
		$('#login_components').css('margin-top','-10px');
		$('#login_components').show();
		$('#error_message').hide();

		$(this).toggleClass('pressed');
		if( login_form.css('display') == 'none' ) {
			login_form.show();
		}

		$('#email').focus();
		event.stopPropagation();
	});

	$('#signup').on('click', function(event) {
		$('#login').removeClass('pressed');
		$('#signup').removeClass('pressed');

		var login_form = $('#login_form');
		
		// sign up specifics
		login_form.css('right', '64px');
		login_form.css('height', '168px');
		$('#signup_components').show();
		$('#signup_components').css('margin-top', '-10px');
		$('#login_components').hide();
		$('#error_message').hide();

		$(this).toggleClass('pressed');
		if( login_form.css('display') == 'none' ) {
			login_form.show();
		}

		$('#signup_fullname').focus();
		
		var time = $('#signup_time');
		time.val('0');
		clearInterval(signup_time);
		signup_time = window.setInterval(function() { time.val(parseInt(time.val()) + 1) } , 1000);

		event.stopPropagation();
	});
	
	$('#login_btn').on('click', function(event) {
		$.post("/actions/login.php", $("#logindata").serialize(), function(data) {
			var json = $.parseJSON(data);
			
			if( json.code == 0 ) {
				location.reload();
				$(window).trigger('statechange');
			} else { 
				$('#login_components').css('margin-top', '10px');
				$('#login_form').css('height', '125px');
				show_and_set_error($('#error_message'), json.msg);
			}
		});
	});

	$('#signup_btn').on('click', function() {
		$.post("/actions/signup.php", $("#signupdata").serialize(), function(data) {
			var json = $.parseJSON(data);
			
			if( json.code == 0 ) {
				// signup successful
				$('#email').val($('#signup_email').val());
				$('#password').val($('#signup_password').val());
				$('#login_btn').trigger('click');
			} else {
				$('#signup_components').css('margin-top', '10px');
				$('#login_form').css('height', '190px');
				show_and_set_error($('#error_message'), json.msg);
			}
		});
	});

	$('#search').on('keyup', function(e, delayval) {
		clearTimeout( search_timeout_id );
		search_timeout_id = null;
		var q =  $('#search').val() || '';
		var cid = curio_id || '';

		// strip bad stuff out
		q = q.replace(/[\?\#\&]/g, "");

		// start loading
		if( q != $('#search').val() )
			$('#loading').show();

		// reset the current page
		pagination = 0;
		
		if( curio_id != '' ) {
			// match fields
			var last_word = q.split(/[\s:]/gi);
			var last_word = last_word[last_word.length - 1];
			
			var i = 0;
			var field = "";
			$('#fields li').each(function() {
				if( starts_with($(this).text().toLowerCase(), last_word.toLowerCase() )) {
					var to_highlight = $(this).text().substring(0, last_word.length );
					$(this).html( $(this).text().replace(to_highlight, "<span class='hl'>" + to_highlight + "</span>") );
					
					field = $(this);
					i++;
				} else {
					$(this).html( $(this).text().replace('<b>','').replace('</b>',''));
				}
			});
			
			var code = (e.keyCode ? e.keyCode : e.which);
			if(code == 13 && i == 1) {
				$('#search').val(q.replace(new RegExp(last_word + '$'), field.text() + ":" ));
				field.toggleClass('hl');
				$('#search').trigger('keyup',[0]);
			}
		}

		delay(function(){
			// search for or within a curio based on cid
			search_curios(q,cid,false);
			search_timeout_id = setTimeout("update_search_hash('" + q + "')", 1000);
		}, delayval );//|| 275 );
	});
	$('#search').trigger('keyup', [200]);
	
	// Results changed 
	$('#results').change( function() {
		if( calc_num_results() == 0 )
		$('#num_results').html(0);
	});

	// ajax hash changes
	$(window).on('hashchange', function(event) {
		event.preventDefault();

		var cid = curio_id || '';
		var q   = event.getState('q')   || '';
		var iid = event.getState('iid') || '';
		var search_bar = $('#search');

		// Showing an instance
		if ( iid != '' ) {
			if( !main_window_showing()) {
				$.ajax({
					type: 'GET',
					url:  '/actions/grab.php',
					data: {q:'getinstancedata', p1:iid},
					success: function(data) {
						var instance_data = $.parseJSON(data);
						curio_id = -1;
						if( instance_data.length > 0) {
							curio_id = instance_data[0].curio_id
							if( curio_width == 0 )
								curio_width = instance_data[0].curio_width;
							if( curio_height == 0 )
								curio_height = instance_data[0].curio_height;
						}

						// show the curio
						show_instance(instance_data, iid);
						$('#search').trigger('keyup');
					}
				});
			}
		} else {
			if( main_window_showing())
				hide_main_window();
		}

		// Searching for a curio
		if( cid == '' ) {
			var curio_info = $('#current_curio');
			curio_info.hide();	
		}

		// Just triggers during onload
		if( first_time == true ) {
			if( (q != '' && q != search_bar.val()) ) {
				search_bar.val(q);
				$('#search').trigger('keyup',[0]);
			}
			first_time = false;
		}

		$('#frompage').attr('value', Base64.encode(window.location.href));
		return false;
	});

	$('#curio_layout').on('resize', function() {
		if( main_window_showing() ) {
			calculateAndSetCurioDims();
			$('#main_window').center();
		}
	});
	
	// Click to add new vertical text element
	$('#curio_add_vtext').on('click', function() {
		$('#window_error_message').fadeOut();
	    $('#curio_layout').append((new curioLayoutTextObject('Text', '', 0, 0, 14, 90, '', MODE_CREATE)).getElement());
	});

	$('#curio_add_picture').on('click', function() {
		$('#window_error_message').fadeOut();
		if( layoutItemsContainsType(ELEM_TYPE.IMAGE) ) {
			show_and_set_error($('#window_error_message'), 'only one picture is supported at this time :(');
		} else {
			$('#curio_layout').append((new curioLayoutPictureObject('Picture', '', 0, 0, 128, 128, '', MODE_CREATE)).getElement());
		}
	});

	$('#curio_add_number').on('click', function() {
		$('#window_error_message').fadeOut();
		var elem = new curioLayoutFloatObject('Number', '', 0, 0, 15, 90, '', MODE_CREATE);
		$('#curio_layout').append(elem.getElement());
	});

	$('#main_window').hover(function(){ 
			mouse_inside = true; 
		}, function() { 
	        mouse_inside = false; 
	});

	$('#close_main_window').on('click', function(event) {
		event.preventDefault();

		var iid = $.bbq.getState('iid') || '';
		var q   = $.bbq.getState('q') || '';

		if( q != null && q != '' ) {
			if( iid != null && iid != '' )
				$.bbq.removeState(['iid']);
		} else {
			var state = {};
    		state['iid'] = '';
    		$.bbq.pushState( state );
    		window.location.hash='!';
		}

		hide_main_window();
		return false;
	});

	// 'threads'
	setInterval("shouldLoadNextPageExtra(500)",1000);
	setInterval("lazyLoadImages()", 300);
});

function show_and_set_error(element, msg) {
	var error_div = element
	error_div.empty();
	error_div.html($('<p/>').toggleClass('med err').text(msg));
	
	if( error_div.css('display') != 'none' ) {
		error_div.fadeOut('fast');
	}
	error_div.fadeIn('fast');
}

function click_body() {
	if( main_window_showing() && !mouse_inside )
		$('#close_main_window').trigger('click');
}

function shouldLoadNextPage() {
	shouldLoadNextPageExtra(0);
}

function shouldLoadNextPageExtra(extra) {
	if  ( calc_num_results() != 0 && !page_loading && 
		  $(window).scrollTop() >= $(document).height() - $(window).height() - extra) {
		if(parseInt(calc_num_results()) % NUM_PAGE === 0) {
			pagination++;
			page_loading = true;
			search_curios($('#search').val(), curio_id, true);
		}
	}
}

function lazyLoadImages() {
	$('#results li img[updated="false"]').each(function(i) { 
		if( isInViewExtra($(this), 300 ) ) {
			var updated_img = img_arr[$(this).attr('order')];
			if( updated_img && updated_img != '' )
				$(this).attr('src', updated_img);
			$(this).attr('updated', 'true');
		}
	});
}

function isInView(elem) {
   	return isInViewExtra(elem, 0);
}

function isInViewExtra(elem, extra) {
	var docViewTop = $(window).scrollTop();
   	var docViewBottom = docViewTop + $(window).height();

   	var elemTop = $(elem).offset().top - extra;
   	var elemBottom = elemTop + $(elem).height() + extra;

   	return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}

function getLimitSize() {
	return NUM_PAGE * num_fields;
}

var delay = (function() {
	var timer = 0;
	return function(callback, ms) {
    	clearTimeout (timer);
    	timer = setTimeout(callback, ms);
  		};
})();

function starts_with(t, s) {
    return t.indexOf(s) == 0;
}

function search_curios(query, cid, append) {
	cid = cid || '';
	
	if( curio_changing == true )
		return;

	if ( last_searched == query && !append )
		return;
	else
		last_searched = query;

	$('#loading').show();

	// Search for a curio
	if( cid == '' ) {
		if( search_req ) 
			search_req.abort();
		search_req = $.ajax({
			type: 'GET',
			url:  '/actions/grab.php',
			data: {q:'getcurios', p1:query},
			success: show_resulting_curios
		});
		
	// Search within a curio	
	} else if( cid != '') {
		if( append == true )
			$('#pageloading').show();

		if( search_req )
			search_req.abort();

		page_loading = true;

		search_req = $.ajax({
			type: 'GET',
			url:  '/actions/grab.php',
			data: {q:'getinstances', p1:query, p2:cid, p3:getLimitSize() , p4:getLimitSize() * pagination},
			success: function(data) { 
				if ( search_timeout_id != null ) 
					show_resulting_instances(data, append); 
			}
		});
		
	// Otherwise
	} if ( query == '') {
		if( $.bbq.getState('q') && $.bbq.getState('q') != '' ) {
			$.bbq.removeState(['q']);
		}

		$('#loading').hide();
	}
}

function update_search_hash(val) {
	if( !val || val == '' )
		return;

	var state = {};
    state['q'] = val;
    $.bbq.pushState( state );
}

function calc_num_results() {
	return $('#results li').size();
}

// global key handlers
$(document).on('keyup', function(e) {
	var code = (e.keyCode ? e.keyCode : e.which);
	if(code == 27) {
		if( main_window_showing() ) {
			$('#close_main_window').trigger('click');
			return false;
		}
	
		if ( $('#login_form').css('display') == 'block' )
			$('#login_form').hide();

		$('#login').removeClass('pressed');
		$('#signup').removeClass('pressed');
		clearInterval(signup_time);
	}
});

$(document).on('click', function(event) {
	if( $('#login_form').css('display') == 'block' ) {
		$('#login').removeClass('pressed');
		$('#signup').removeClass('pressed');
		$('#login_form').hide();
		$('#error_message').hide();
		clearInterval(signup_time);
	}
});

// Order is type;x;y;h;w;field_id;value
function calculateAndSetProperties(type, shell, content, value, field_id) {
	value = value ? value : "";
	return type + ';' +
		   parseInt(shell.css('left')) + ';' + 
		   parseInt(shell.css('top')) + ';' + 
		   parseInt(content.css('height')) + ';' + 
		   parseInt(content.css('width')) + ';' + 
		   field_id + ';' +
		   (shell.mode != MODE_CREATE ? Base64.encode(value) : "");
}

function calculateAndSetName(obj) {
	return setFieldName(obj.attr('value'));
}

function fieldPrefix() {
	return '__cl__';
}

function setFieldName(val) {
	return fieldPrefix() + val;
}

Function.prototype.inherits_from = function(parent_class) {  
	this.prototype = new parent_class;
	this.prototype.constructor = this;
	this.prototype.parent = parent_class;
	return this;
}

function curioLayoutObject(name, value, x, y, h, w, fid, layoutMode) {
	this.new_elem = null;
	this.name = name;
	this.x = parseInt(x);
	this.y = parseInt(y);
	this.height = parseInt(h);
	this.width = parseInt(w);
	this.mode = layoutMode;
	this.value = value;
	this.fid = fid;
	this.type = null;

	// Delete button
	this.del = $('<div>x</div>').addClass('delete_button');
    this.del.on('click', function() {
        $(this).parents("div:first").remove();
    });

    this.getElement = function() {
    	return this.new_elem;
    }

    this.setType = function(t) {
    	this.type = t;
    }

    this.update = function() {
    	if( this.new_elem )
    		this.new_elem.trigger('resize');
    }
}

curioLayoutPictureObject.inherits_from(curioLayoutObject);
function curioLayoutPictureObject(name, value, x, y, h, w, fid, layoutMode) {
	this.parent.call(this, name, value, x, y, h, w, fid, layoutMode);
	this.type = ELEM_TYPE.IMAGE;

	// New picture element
	this.new_elem = $('<div><input class="no_style" id="title_value" type="text" value="' + this.name + '" /></div>').addClass('picture_element').addClass('cl');
	this.new_elem.css('left', this.x );
	this.new_elem.css('top', this.y );
	this.new_elem.css('height', this.height);
	this.new_elem.css('width', this.width);

	this.image = $('<img/>').addClass('stretch');
	this.image.attr('src', get_med_image(this.value));
	this.new_elem.append(this.image);

	// hax - hide title until figure out what to do with it
	$('#title_value',this.new_pic).show();

	// Hidden input for form submission
	this.layout = $('<input/>').attr({
		type: 'hidden',
		name: calculateAndSetName($('#title_value', this.new_elem)),
		id: calculateAndSetName($('#title_value', this.new_elem)),
		value: calculateAndSetProperties(this.type, this.new_elem, this.new_elem, this.value, this.fid)
	});
	this.new_elem.append(this.layout);

	// Remove junk
	this.new_elem.css('border','1px solid transparent');

	switch( this.mode ) {
		case MODE_EDIT:
		case MODE_CREATE:
			// Delete button
			this.new_elem.append(this.del);
			this.image.hide();
		
			this.new_elem.draggable({
				containment: $('#curio_layout'),
				drag: $.proxy(function() {
					this.layout.attr('value', calculateAndSetProperties(this.type, this.new_elem, 
																		this.new_elem, this.image.attr('src'), 
																		this.fid));
				},this),
				grid: [5,5]
			});

			// Temporary -- not really sure best way to handle resizing images during MODE_EDIT
			if( this.mode == MODE_CREATE ) {
				this.new_elem.resizable({
					resize: $.proxy(function() {
						this.layout.attr('value', calculateAndSetProperties(this.type, this.new_elem, 
																			this.new_elem, this.image.attr('src'), 
																			this.fid));
					},this),
					autoHide: true,
					containment: $('#curio_layout'),
					minHeight: 128,
					minWidth: 128,
					grid: 5
			    });
			}

		    this.new_elem.addClass('hover');

			break;
		case MODE_PRES:
			this.image.show();
			this.image.on('click', $.proxy(function() {
				window.open(this.value);
			},this));

			// hax - hide title until figure out what to do with it
			$('#title_value',this.new_elem).hide();

			
		case MODE_ADD:
			// Form
			this.image.show();
			if( getUID() != "-1") {
				this.image_form = $('<form action="/actions/upload_image.php" method="post" enctype="multipart/form-data" class="image_form"/>');
				
				this.image_form.append('<input type="hidden" name="field_height" value="'+this.height+'" />');
				this.image_form.append('<input type="hidden" name="field_width" value="'+this.width+'" />');

				// upload image
				this.image_form.ajaxForm({
					success: $.proxy(function(data) {
						var json = $.parseJSON(data);

						// If no error, then msg is the actual image url
						if( json.code == 0 ) {
							$('#window_error_message').hide();
							this.layout.attr('value', calculateAndSetProperties(this.type, this.new_elem, 
																				this.new_elem, json.msg, this.fid));
							
							this.value = json.msg;
							this.image.attr('src', get_med_image(json.msg));

							this.new_elem.trigger('keyup');

						} else {
							show_and_set_error($('#window_error_message'), json.msg);
						}
					},this)
				});

				this.image_form.submit( $.proxy(function(event) {
				 	$(this).ajaxSubmit(); 
				 	return false;
				},this));

				// Image input
				this.image_upload_input = $('<input size="1" type="file" name="file" />').addClass("file_upload");
				this.image_upload_input.change( $.proxy(function() {
					this.image_form.trigger('submit');
				},this));

				this.image_form.append(this.image_upload_input);
				this.new_elem.append(this.image_form);
			}

			// hax - hide title until figure out what to do with it
			$('#title_value',this.new_elem).hide();

			break;
	}

    this.new_elem.hover(
         $.proxy(function() {
            this.del.show();
			if( this.image.css('display') != 'none' && this.image_form ) this.image_form.show();
        }, this),
        $.proxy(function() {
            this.del.hide();
			if( this.image.css('display') != 'none' && this.image_form )this.image_form.hide();
        }, this)
    );
}

curioLayoutTextObject.inherits_from(curioLayoutObject);
function curioLayoutTextObject(name, value, x, y, h, w, fid, layoutMode) {
	this.parent.call(this, name, value, x, y, h, w, fid, layoutMode);
	this.type = ELEM_TYPE.STRING;
	
	// New element
	this.new_elem = $('<div/>').addClass('text_element').addClass('cl');
	this.new_elem.css('left', this.x );
	this.new_elem.css('top', this.y);
	this.new_elem.css('height', this.height + 30);
	this.new_elem.css('width', this.width + 10);
	this.new_elem.append('<div><input class="no_style" id="title_value" type="text" value=' + this.name + ' /></div>').addClass('text_title');
	
	// Text value
    this.new_text_value = $('<div>'+filler+'</div>').addClass('text_value').addClass('wordwrap').wrap('<pre/>');;
	this.new_text_value.css('height', this.height);
	this.new_text_value.css('width', this.width);
    this.new_elem.append(this.new_text_value)

	// Remove resizeable junk
	this.new_text_value.css('border','1px solid transparent');

	switch( this.mode ) {
		case MODE_EDIT:
		case MODE_CREATE:
			this.new_elem.addClass('hover');

			// Delete button
			this.new_elem.append(this.del);
		
			// Properties
	        this.new_elem.draggable({ 
				containment: $('#curio_layout'),
				drag: $.proxy(function() {
					this.layout.attr('value', calculateAndSetProperties(this.type, this.new_elem, 
																		this.new_text_value, this.new_text_value.text(), 
																		this.fid));
				},this),
				grid: [5,5]
			});
			
			this.new_elem.resizable({
				containment: $('#curio_layout'),
				autoHide: true,
				alsoResize: this.new_text_value,
		        minHeight: 45,
		        minWidth: 80,
		        grid: 5
		    });

			this.new_elem.hover( 
	            $.proxy(function() {
	                this.del.show();
	            }, this),

	            $.proxy(function() {
	            	this.del.hide();
	            }, this)
	        );
			break;
		case MODE_PRES:
			this.new_text_value.html(highlight_matched_fields($('#search').val(),this.value));
			this.new_text_value.css('background-color','white');
			$('#title_value', this.new_elem).attr('readonly', 'readonly');
			$('.no_style:hover', this).css('background-color','');
			
			if( getUID() != "-1") {
				this.new_text_value.attr('contentEditable', true);
				this.new_text_value.addClass('pres');	    		
	    	}

			break;
		case MODE_ADD:
			this.new_text_value.empty();
			this.new_text_value.addClass('addto');
			
			this.new_text_value.attr('contentEditable', true);
			$('#title_value', this.new_elem).attr('readonly', 'readonly');		
			
			this.new_text_value.on('keyup', $.proxy(function() {
				this.layout.attr('value', calculateAndSetProperties(this.type, this.new_elem, 
																	this.new_text_value, this.new_text_value.html(), 
																	this.fid));
			},this));
			break;
		default:
			break;

		this.getValue = function() {
			return this.new_text_value;
		}
	}
    
	// Hidden input for form submission
	this.layout = $('<input/>').attr({
		type: 'hidden',
		name: calculateAndSetName($('#title_value', this.new_elem)),
		id: calculateAndSetName($('#title_value', this.new_elem)),
		value: calculateAndSetProperties(this.type, this.new_elem, this.new_text_value, 
										this.new_text_value.text(), this.fid)
	});
	this.new_elem.append(this.layout);

	// If we resize the content, then update the hidden element for height and width
	this.new_elem.on('resize', $.proxy(function() {
		this.layout.attr('value', calculateAndSetProperties(this.type, this.new_elem, 
															this.new_text_value, this.new_text_value.text(), 
															this.fid))
	},this));
	
	// If we change the name, then update the hidden element for the name
	$('#title_value', this.new_elem).on('keyup', $.proxy(function() {
		this.layout.attr('name', calculateAndSetName($('#title_value', this.new_elem)));
	}, this ));
}

curioLayoutFloatObject = function(name, value, x, y, h, w, fid, layoutMode) { 
	var e = new curioLayoutTextObject(name, value, x, y, h, w, fid, layoutMode);
	e.type = ELEM_TYPE.FLOAT;
	e.update();
	return e;
}

function getUID() {
	return $('#uid').text();
}

function getFieldPropertiesFromDiv(div) {
	return $('input[id^="'+fieldPrefix()+'"]', div).val();
}

function getFieldType(fieldProperties) {
	if (!fieldProperties || typeof fieldProperties === "undefined")
		return "";
	
	return parseInt(fieldProperties.split(";")[0]);
}

function getNumLayoutItems() {
	return getLayoutItems().size();
}

function detachLayoutItems() {
	getLayoutItems().each(function(i) {
		$(this).detach();
	});
}

function layoutItemsContainsType(type) {
	var result = false;
	getLayoutItems().each(function(i) {
		if( getFieldType(getFieldPropertiesFromDiv($(this))) == type )
			result = true;
	});
	return result;
}

function getLayoutItems() {
	return $('#curio_layout div.cl');
}

function processLayout(elements, mode) {
	var clLayout = $('#curio_layout');

	if( elements.length > 0 ) {
		clLayout.css('height', curio_height );
		clLayout.css('width', curio_width );
	}
	
	for( var i = 0; i < elements.length; ++i ) {
		var elem = elements[i];
		var new_elem;

		switch(parseInt(elem.format_id)) {
			case ELEM_TYPE.FLOAT:
				var new_elem = new curioLayoutFloatObject(elem.name || '', elem.value || '',
															elem.x, elem.y, elem.h, elem.w,
															elem.field_id, mode );
				break;
			case ELEM_TYPE.STRING:
				var new_elem = new curioLayoutTextObject( elem.name || '', elem.value || '', 
														  elem.x, elem.y, elem.h, elem.w, 
														  elem.field_id, mode );
				break;
			case ELEM_TYPE.IMAGE:
				var new_elem = new curioLayoutPictureObject( elem.name || '', elem.value || '', 
														     elem.x, elem.y, elem.h, elem.w, 
														     elem.field_id, mode );
				break;
		}

		if( mode == MODE_PRES ) {
			new_elem.getElement().on('keyup',
				elem_key_helper(elem.name, elem.value, parseInt(elem.format_id))
			);
		}

		$('#curio_layout').append(new_elem.getElement());
	}

	return true;
}

function elem_key_helper(name, orig, type) {
	return function() {
		var o = orig;
		var old_change_counter = change_counter;
		var text_elem = '';
		var new_text = '';

		switch ( type ) {
			case ELEM_TYPE.FLOAT:
			case ELEM_TYPE.STRING:
				text_elem = $('.text_value',this);

				// remove span tags but keep content
				$('span',text_elem).each( function(i) { 
					if( $(this).html() == "" )
						$(this).remove();
					else
						$(this).unwrap();
					
				});
				new_text = text_elem.html();

				var new_val = updated_field_value($("'#" + setFieldName(name) + "'",this).val(), new_text);
				$("'#" + setFieldName(name) + "'",this).val(new_val);
				break;
			case ELEM_TYPE.IMAGE:
				// this is the img
				text_elem = $('.stretch', this);
				new_text = text_elem.attr('src');
				break;
		}

		if (!is_changed(text_elem) && o != new_text) {
			change_counter++;
			$('#create_new').val('save');
			text_elem.attr('set', '1');
			 
		} else if (is_changed(text_elem) && o == new_text) {
			change_counter--;
			text_elem.removeAttr('set');
		}

		if( is_changed(text_elem) && change_counter != old_change_counter && change_counter > 0 ) {
			$('#create_new').fadeIn('fast');
			center_main_window();
		} else if (!is_changed(text_elem) && change_counter == 0 ) {
			$('#create_new').fadeOut('fast');
			center_main_window();
		}
	}
}

function is_changed(element) {
	return typeof element.attr('set') != 'undefined';
}

function reset_changed_elements() {
	getLayoutItems().each(function(i) {
		$(this).removeAttr('set');
		$(this).keyup();
	});
}

function updated_field_value(str, val) {
	return str.substring(0, str.lastIndexOf(';') + 1) + Base64.encode(val);
}

function calculateAndSetCurioDims() {
	$('#curio_height').attr('value', parseInt($('#curio_layout').css('height')));
	$('#curio_width').attr('value', parseInt($('#curio_layout').css('width')));
}

jQuery.fn.center = function () {
    this.css("position", "absolute");

    // Edge case if the window can't be centered
    if( $(window).height() < this.outerHeight() ) 
    	this.css("top", "20px");
    else
    	this.css("top", (($(window).height() - this.outerHeight()) / 2) + $(window).scrollTop() + "px");
    this.css("left", (($(window).width() - this.outerWidth()) / 2) + $(window).scrollLeft() + "px");
    return this;
}

jQuery.fn.centerFixed = function () {
    this.css("position", "fixed");

    // Edge case if the window can't be centered
    if( $(window).height() < this.outerHeight() ) 
    	this.css("top", "20px");
    else
    	this.css("top", (($(window).height() - this.outerHeight()) / 2) + "px");
    this.css("left", (($(window).width() - this.outerWidth()) / 2) + $(window).scrollLeft() + "px");
    return this;
}

jQuery.fn.outerHTML = function(s) {
	return ($('<div>').append(this).clone()).remove().html();
}

jQuery.fn.unwrapChildren = function() {
	return this.contents().unwrap();
}

function center_main_window() {
	$('#main_window').centerFixed();
}

function show_main_window(absolute) {
	var win = $('#main_window');
	calculateAndSetCurioDims();
	$('#window_error_message').hide();

	// Center and show window
	if( absolute === true )
		$('#main_window').center();
	else
		$('#main_window').centerFixed();
	
	win.fadeIn('fast', delay(function() { 
		$('body').on('mousedown', click_body) 
	},500));
	$('#darkness').fadeIn('fast');

	$('#frompage').attr('value', Base64.encode(window.location.href));
}

function hide_main_window() {
	$('#main_window').fadeOut('fast', delay(function() { 
		$('body').off('mousedown', click_body) 
	},500));
	$('#darkness').fadeOut('fast');

	delay(function() {
		detachLayoutItems();
	}, 200);

	return false;
}

function main_window_showing() {
	return $('#main_window').css('display') != 'none';
}

// match instance field with search str
function highlight_matched_fields(search, fieldval) {
	if( fieldval == null)
		return;

	if( search == "" )
		return fieldval;
	
	var query_words = search.split(/[\s:\<\>]/gi);
	var new_val = fieldval;
	for( var i = 0; i < query_words.length; ++i ) {
		if( fieldval.toLowerCase().indexOf(query_words[i].toLowerCase()) != -1 ) {
			var re = new RegExp("(" + encodeURIComponent(query_words[i]) + ")", "i");
			new_val = new_val.replace(re, "<span class='matched_field'>$1</span>");
		}
	}
	
	return new_val;
}

String.prototype.specialInsert = function( position, s ) {
    return (this.slice(0,position) + s + this.slice(position ));
};

// Basically just prefixes an 's'
function get_small_image(path) {
	return get_smaller(path, 's');
}

function get_med_image(path) {
	return get_smaller(path, 'm');
}

function get_smaller(path, val) {
	return path ? path.specialInsert(path.lastIndexOf('/') + 1, val) : '';
}

function show_resulting_instances(data, append) {
	var instances = $.parseJSON(data);
	var results = $('#results');
	var search = $('#search').val();
	var has_image = false;
	var result_str = "";

	if (append == false) {
		results.empty();
		results.change();
		img_arr.length = 0;
		img_arr = [];
		img_counter = 0;
	}

	// INSTANCES
	for( var i = 0; i < instances.length; ++i ) {

		var instance_elems = instances[i];
		var image_set = false;
		var instance_id;
		var new_item_image_content = "";
		//var new_item_content = $('<p/>').toggleClass('content');
		var inner_content = ""
		//var layout_elements = [];

		// FIELDS
		for( var j = 0; j < instance_elems.length; ++j ) {
			var value = instance_elems[j].value || '';
			value = value.replace(/\<br\>/g,' ');
			switch (parseInt(instance_elems[j].format_id)) {
				case ELEM_TYPE.IMAGE:
					// Kinda hack - display the first pic element if there is one
					if( !image_set ) {
						var small_image = get_small_image(value);
						new_item_image_content += ($('<img src="'+DEFAULT_IMG+'"/>').attr('order', img_counter++).attr('updated','false')).outerHTML();
						img_arr.push(small_image);
						has_image = image_set = true;
					}
					break;
				default:
					// Try to highlight the content. If it matches, then display it in the results, otherwise, don't show it
					var hlContent = highlight_matched_fields(search, value);
					if( search == "" || (hlContent != value && hlContent != "") ) 
						inner_content += hlContent + " ";
					break;
			}
			
			instance_id = instance_elems[j].instance_id;
		}
		var new_item_content = "<p class='content'>" + inner_content + "</p>";

		result_str += "<a href='#iid="+instance_id+"'><li"+(has_image ? " class='grid'" : "")+">" + new_item_image_content + new_item_content + "</li></a>";
	}

	results.append(result_str);

	$('#num_results').html(calc_num_results());

	$('#loading').hide();
	$('#pageloading').hide();
	page_loading = false;
}

function show_instance_handler(layout_items, iid) {
	return function() {
    	show_instance(layout_items, iid);
    	return false;
	}
}

function show_instance(layout_items, iid) {
	change_counter = 0;

	var main_window = $('#main_window');
	main_window.css('height','auto');
	main_window.css('width', 'auto');
	
	$('#create_curio_components').hide();

	var clLayout = $('#curio_layout');
	clLayout.show();
	clLayout.css('background-color', '#FFF');
	clLayout.css('border', '0px solid #D6D6D6');
	clLayout.resizable('destroy');
	
	$('#create_new').hide();
	$('#create_new').val('save');
	$('#iid').val(iid);
	
	// Clear the title
	$('#main_window_title').empty();
	
	processLayout(layout_items, MODE_PRES);
	$('#close_main_window').hide();
	show_main_window();

	var state = {};
   	state['iid'] = iid;
    $.bbq.pushState( state );
    $('#FORM_MODE').attr('value', MODE_INSTANCE);

    layout_items = null;

    return false;
}

function show_resulting_curios(data) {
	var curios = $.parseJSON(data);
	var results = $('#results');
	
	// Clear results
	results.empty();

	// Update results
	$('#num_results').html(curios.length);
	
	for( var i = 0; i < curios.length; i++ ) {
		var new_link = $('<a/>');
		var new_item = $('<li/>');

		var title = curios[i].title;
		var uid = curios[i].user_id;
		var priv = curios[i].private;

		if( priv == "1" ) {
			new_link.attr('href', uid + '/' + fix_title(title) + '/');
			new_item.addClass('private');
		} else {
			new_link.attr('href', fix_title(title) + '/');
		}

	/*	new_item.on('click', 
			function(event) { 
				var t = title;
				if(event.ctrlKey || event.metaKey)
					return true
				else
					nav_handler(t, uid);
				t = null; 
			}
		);*/

		new_item.append( $("<div/>").toggleClass('curio title').append(curios[i].title + ' (').append($("<span/>").toggleClass('curio info value').append( curios[i].entries )).append(')'));
		new_item.append( $("<p/>").toggleClass('curio info small').css('width','600px').append(curios[i].description) );

		new_link.append(new_item);
		results.append(new_link);
		new_item = null;
		new_item = null;
	}

	$('#loading').hide();
}

function url_change(name, uid) {
//	History.pushState(null, 'curio/' + name , "/" + (uid === undefined || uid == '-1' ? '' : '/' + uid + '/') + fix_title(name) + "/#iid=");
}

function nav_handler(name, uid) { 
		return function() { 
			var n = name;
			$('#search').val('');
			$('#results').empty();
			return false;
	}; 
}

function nav_to_curio(curio, uid) {
	clearTimeout( search_timeout_id );
	search_timeout_id = null;
	if( search_req ) search_req.abort();
	search_req = null;

	if ( uid === undefined ) {
		uid = '-1';
	}

	curio_name = curio;
	curio_desc = "";
	curio_id = '';

	$('#results').change();

	if( curio == null ) {
		$('#field_list').empty();
		$('#current_curio').hide();
		$('#addentry').hide();
		$('#editcurio').hide();
		$('#results').empty();
		return false;
	}

	$('#loading').show();

	$('#addentry').show();
	$('#editcurio').show();

	if( main_window_showing() )
		hide_main_window();

	if( curio_changing == true )
		return false;
	else
		curio_changing = true;
	
	$('#search').val('');
	last_searched = null;

	// Change the URL
	//if( uid != '-1')
	//	url_change(curio);
	//else
	//	url_change(curio, uid);

	// Set curio title, height / width
	// Set search fields
	$.ajax({
		type: 'GET',
		url:  '/actions/grab.php',
		aysnc: false,
		data: {q:'getcuriobyname', p1:curio, p2:uid},
		success: function(data) { 
			var curio_data = $.parseJSON(data);
			if( curio_data != null && curio_data.length > 0 ) {
				$('#cid').val(curio_data[0].curio_id);

				// Set curio title
				var curio_info = $('#current_curio');
				curio_info.css('display','inline-block');

				curio_id   = curio_data[0].curio_id;
				curio_desc = curio_data[0].description;
				curio_height = curio_data[0].height;
				curio_width  = curio_data[0].width;
				curio_info.html(curio);
			}
			
			// Set fields
			var fields = $('#field_list');
			fields.empty();
			for(var i = 0; i < curio_data.length; ++i) {
				switch( parseInt(curio_data[i].format_id) ) {
					case ELEM_TYPE.FLOAT:
					case ELEM_TYPE.STRING:
						var item = $('<li/>');

						item.on('click', clickfield_handler(curio_data[i].fieldname));
						item.html(curio_data[i].fieldname);
						fields.append(item);
						item = null;
					default:
						break;
				}
			}
			// num_fields used by search limit
			num_fields = i;

			document.title = 'curio/' + curio;

			setTimeout(function() { $('#search').focus() }, 150);
			$('#search').trigger('keyup', [0]);
			curio_changing = false;
		}
	});

    return false;
}

function clickfield_handler(field) { return function() { click_field(field); field = null; }; }
function click_field(field) {
	// add space if necessary
	var str = $('#search').val()
	str = str.charAt(str.length - 1) == ' ' || str.length == 0  ? '' : ' ';
	$('#search').val($('#search').val() + str + field + ":");
	$('#search').focus();
}

function fix_title(t) {
	return t.replace(/\s/g,'_');
}

function unfix_title(t) {
	return t.replace(/_/g,' ');
}
