// global variable stores note ID for videomarking
// set to 0 when toolbox is in video panel mode
var toolboxNoteID = 0;
var StateManager = EXANIMO.managers.StateManager;

// Why does StateManager not allow you to peek at the current page?
var gCurrState = null;


function getQueryParams(qpStr) {
	var args = new Object();
	var pairs = qpStr.substring(1).split("&");
	for (var i = 0; i < pairs.length; i++) {
		var p = pairs[i];
		var pos = p.indexOf('=');
		if (pos >= 0) {
			var argname = p.substring(0,pos);
			var value = p.substring(pos + 1); 
			value = decodeURIComponent(value); 
			args[argname] = value; 
		}
	} 
	return args;
};

// Like $.post, but with a failure callback
function post(url, params, success, failure) {
	$.ajax({'url':url, 'type':'POST', 'data':params, 'dataType':'text',
			'success':success, 'error':failure});
};

StateManager.onstatechange = function(e) {
    // Tweak StateManager to allow peeking at current state.
    gCurrState = e.id;
};

function parseStateString(s) {
    var result = ['defaultState', []];
    if ((s != null) && (s != 'defaultState')) {
        var fields = s.split(",");
        if (fields) {
            result = [fields[0], fields.slice(1)];
        }
    }
    return result;
};

function getToolboxState() {
    var result = [];
    var state = parseStateString(gCurrState);
    if (state[0] == "toolbox") {
        result = state[1];
    }
    return result;
};

StateManager.onstaterevisit = function(e) {
	// IE misbehaves when asked to initiate an Ajax call within an
	// Ajax callback.
	function deferredStateRevisit() {
	    var state = parseStateString(e.id);
		if (state[0] == 'defaultState') {
			$('#toolbox').load('/note_default/');
			$('#video-player').load('/video_default/');
		} else {
			// First param determines method
			// Successive params are args to pass to the method
		    switch (state[0]) {
		        case 'videobox':
		        loadVideoNoSetState.apply(this, state[1]);
		        break;
		        
		        case 'toolbox':
		        loadToolboxNoSetState.apply(this, state[1]);
		        break;
		    }
		}
	};
    window.setTimeout(deferredStateRevisit, 10);
};	  

// Loads video panel
// Only videoID is required
function loadVideoNoSetState(videoID, channelID) {
	var url = '/video/' + videoID + '/';
	var params = videoID;
	
	var setRating = function(val) {
		var rating_field = $('#id_rating');
		rating_field.val(val);
		saveRatings(url);
	};
	
	var attachEvents = function(t){
		$('#id_rating').change(function() {
		   saveRatings(url);
		});
		var fav_field = $('#id_favorite');
		$('#fav_link').click(function() {
		  fav_field.val('1');
		  saveRatings(url);
		});
		var rating_field = $('#id_rating');
		if (rating_field.val() == 'None') {
			rating_field.val(0);
		}
		var s = $('#id_stars').Stars({
			maxRating: 5,
			container: $('#id_stars'),
			imagePath: '/site_media/img/stars/',
			value: rating_field.val(),
			callback: setRating
		});
	};
	
	$('#video-player').load(url, attachEvents);
	if (toolboxNoteID == 0 && channelID != null) {
		// Load channel
		// loadToolbox('/channel',channelID);
		$('#toolbox').load('/channel/' + channelID + '/');
		params += ',' + channelID;
	}
	var login_form = $('#login_form');
	if (login_form != null) {
		login_form.action = '#videobox,' + params;
	}
	return ('videobox,' + params);
};

function loadVideo() {
    var newState = loadVideoNoSetState.apply(arguments.callee, arguments);
    StateManager.setState(newState);
};

// Loads note and video list toolbox
// Only obj is required
// TODO:  Refactor to accept an arbitrary url (obj) with query params.
function loadToolboxNoSetState(obj, id, pg, sort, extraParamsStr) {
    var path = obj;
    var queryParams = {};
    
    // Extract query parameters.
    var m = obj.match(/\?.*$/);
    if (m != null) {
        queryParams = getQueryParams(m[0]);
        path = obj.match(/^[^?]*/)[0];
        obj = path;
    }
    
    if (extraParamsStr) {
        var epItems = extraParamsStr.split('\\');
        $(epItems).each(function() {
            var fields = this.split('=');
            if (fields.length == 2) {
                queryParams[fields[0]] = fields[1];
            }
        });
    }
    
    if (!obj.match(/^\//)) {
        path = '/' + obj;
    }
    if (!obj.match(/\/$/)) {
        path = obj + '/';
    }
	// TODO Find a more elegant way to track submitted parameters
	var params = obj;
	if (id != null && id != 0) {
		path += id + '/';
		params += ',' + id;
	} else if (id == 0) {
		// channelID is 0 when paginating favorites or history
		params += ',' + id;
	} else if ((id == null) || (id == "")) {
	    params += ",";
	}
	var querySep = '?';
	function newQP(name, value) {
	    var result = querySep + name + "=" + value;
	    querySep = '&';
	    return result;
	};
	if ((pg != null) && (pg != "")) {
		path += newQP('page', pg);
		params += ',' + pg;
	} else {
	    params += ",";
	}
	// sort parameter requires pg
	if (sort != null && sort != '') {
		// sort is empty when paginating favorites or history
		path += newQP('sort', sort);
		params += ',' + sort;
	} else {
	    params += ",";
	}
	var qpItems = [];
	for (var key in queryParams) {
	    var value = queryParams[key];
	    path += newQP(key, value);
	    qpItems.push('' + key + '=' + value);
	}
	// TODO:  Use a JSON string..
	params += ',' + qpItems.join('\\');
	
	$('#toolbox').load(path);
	// TODO add tab highlighting (and remove tabs from sub-templates)?
	if (obj == 'note' && id != null) {
		toolboxNoteID = id;
	} else if (obj == '/note/add') {
		toolboxNoteID = -1;
	} else {
		toolboxNoteID = 0;
	}
	var login_form = $('#login_form');
	if (login_form != null) {
		login_form.action = '#toolbox,' + params;
	}
    return ('toolbox,' + params);
};

function loadToolbox() {
    var state = loadToolboxNoSetState.apply(arguments.callee, arguments);
    StateManager.setState(state);
};

function loadToolboxPage(pageParams) {
    var current = getToolboxState();
    var pg = pageParams.replace(/\?page=/, "");
    var args = [current[0], current[1], pg, current[3]];
    return loadToolbox.apply(arguments.callee, args);
};

function saveNote(actionURL){

    // fetch the content of the text area
	var content = $('#id_content').val();

	// display saving message
	var msg = $('#id_msg');
    

	msg.addClass('saving');
	msg.html('Saving note');
	
	// display saved message (until user clicks away)
	var displaySavedMsg = function(t){
		msg.html('Note saved.');
		msg.removeClass('saving');
		$('#id_content').click(function() {
		  msg.html("");
		});
	};

	var email = '';
    if ($('#id_email_note')) {
        email = $('#id_email_note').val();

    }
	
	// make the ajax connection
	var success = function(response, status){
		// there may be a better way to do this
		if (isNaN(response)) {
			response = (response == null) ? "" : response;
			msg.html(response);
		} else {
			toolboxNoteID = response;
			$('#toolbox').load('/note/' + toolboxNoteID + '/', displaySavedMsg);
            $('#id_email_note').val(email);
		}
		msg.removeClass('saving');
	};

	var failure = function(t) {
		msg.html('Sorry, the update failed.'); 
		msg.removeClass('saving');
	};
	
	var url	 = actionURL;
	var title = '';
	if ($('#id_title')) {
		// this is needed so as not to wipe out existing or new note title
		title = $('#id_title').val();
	} else {
		title = ' ';
	}
    var tagsField = $('#note_tags');
	var note_tags = tagsField.val();
	var params = {
		"content": content,
		"title": title,
		"tags": note_tags,
        "email": email
	};

	post(url, params, success, failure);
};

function saveURL(actionURL){
	var note_url = $('#id_url').val();
	var note_tags = $('#tags').val();
	var msg = $('#id_msg');
	msg.addClass('saving');
	msg.html('Saving bookmark');

	var success = function(response, status){ 
		if (isNaN(response)) {
			msg.html(response);
		} else {
			toolboxNoteID = response;
			msg.html('Bookmark saved.');
			$('#toolbox').load('/note/' + toolboxNoteID + '/');
		}
		msg.removeClass('saving');
	};
	var failure = function(t){
		msg.html('Sorry, the update failed.');
		msg.removeClass('saving');
	};
	
	var url	 = actionURL;
	// this is needed so as not to wipe out existing or new note content
	var content = $('#id_content').val();
	if (content != '') {
		params += '&content=' + content;
	}
	var title = 'Veezyon Note' ;
	if ($('#id_title').val()) {
		// this is needed so as not to wipe out existing or new note title
		title = $('#id_title').val();
	}	  
	
	var note_tags = $('#tags').val();

	var params = {
		"url": note_url,
		"title": title,
		"tags": note_tags
	};
	if (content != '') {
		params['content'] = content;
	}
	post(url, params, success, failure);
};

function saveRatings(actionURL){
	// fetch the content of the form inputs
	var rating = $('#id_rating').val();
	var favorite = $('#id_favorite').val();
	var tags = $('#tags').val();

	var msg = $('#id_video_msg');
	msg.addClass('saving');
	msg.html('Saving');
	
	var success = function(response, status){ 
		msg.html('Saved.');
		msg.removeClass('saving');
		// TODO: Refresh my tags, in case they changed.
		// Could ask the server to send it as part of the response...
		var url = actionURL + 'tags/';
		$('#tags_id').load(url);
	};

	var failure = function(t) { 
		msg.html('Sorry, the update failed.'); 
		msg.removeClass('saving');
	};
	
	var url	 = actionURL;
	var params = {
		"rating": rating,
		"tags": tags
	};
	if (favorite == '1') {
		params['favorite'] = favorite;
	}
	post(url, params, success, failure);
};

function saveVideoMark(videoID) {
	if (toolboxNoteID == 0) {
		loadToolbox('/note/add');
	}
	var msg = $('#id_video_msg');
	msg.addClass('saving');
	msg.html('Saving');

	var success = function(response, status){ 
		if (isNaN(response)) {
			response = (response == null) ? "" : response;
			msg.html(response);
		} else {
			toolboxNoteID = response;
			msg.html('Saved.');
			$('#toolbox').load('/note/' + toolboxNoteID + '/');
		}
		msg.removeClass('saving');
	};
	var failure = function(t){ 
		msg.html('<div class="error">Sorry, the update failed.</div>');	  
		msg.removeClass('saving');
	};
	
	var url = '/videomark/add/';
	var params = {
		"video_id": videoID
	};
	if (toolboxNoteID != -1) {
		params['note_id'] = toolboxNoteID;
	}
	// content field may not exist if toolbox is in video panel mode
	if ($('#id_content')) {
		// this is needed so as not to wipe out existing or new note content
		var content = $('#id_content').text();
		if (content != '') {
			params['content'] = content;
		}
	}	
	if ($('#id_title').length > 0) {
		// this is needed so as not to wipe out existing or new note title
		var title = $('#id_title').val();
		if (title != '') {
			params['title'] = title;
		}
	}
	
	post(url, params, success, failure);
};

function searchRedirect(searchType) {
	var search_criteria = $(searchType).val();
	if (search_criteria != '') {
		var obj = 'Video';
		if (searchType == 'note_search') {
			obj = 'Note';
		}
		var path = '/search/?q=' + search_criteria + '&o=' + obj;
		if (searchType == 'video_search') {
			var channel = $('#channel').val();
			var provider = $('#provider').val();
			if (channel != undefined && channel != '')
				path += '&c=' + channel;
			if (provider != undefined && provider != '')
				path += '&p=' + provider;
		}
		
		loadToolbox(path);
	}
	return false;
};

// Checks for search parameters in the querystring in case another page initiated
function checkForSearch() {
	params = getQueryParams(location.search);
	var searchParam = params['search'];
	if (searchParam != undefined && searchParam != '') {
		var path = '/search/?q=' + searchParam + '&o=Video';
		var channelParam = params['channel'];
		if (channelParam != '' && channelParam != undefined)
			path += '&c=' + channelParam;
		var providerParam = params['provider'];
		if (providerParam != '' && providerParam != undefined)
			path += '&p=' + providerParam;
		$('#toolbox').load(path);
	}
};

function shareLinks(obj, id){
	var email = $('#id_email_note').val();
	var links = '';
	var msg = $('#id_msg');

	if (id == null) {
		// User is sharing one or more notes
		var checked_notes = [];
		$('#note_referral_form :checkbox[checked]').each(function() {
			checked_notes.push($(this).val());
		});
		id = checked_notes.join(",");
	} else if (obj == 'note') {
		msg = $('#id_note_share_msg');
	} else if (obj == 'video') {
		msg = $('#id_video_share_msg');
	    email = $('#id_email').val();
	}
		
	if (id != null && id != '') {
		msg.addClass('saving');
		msg.html('Sending message');
	
		var success = function(response, status) {
			msg.html(response); 
			msg.removeClass('saving');
		};
		var failure = function(t) {
			msg.html('Sorry, could not send the message.');
			msg.removeClass('saving');
		};
		
		var url = '/share/';
		var params = {"email": email, "obj": obj, "id":id};
		post(url, params, success, failure);
	}
};

function shareNotesByID(checked_notes, msg, email) {
    msg.addClass('saving');
    msg.html('Sending message');

    var success = function(response, status) {
        msg.html(response); 
        msg.removeClass('saving');
    };
    var failure = function(t) {
        msg.html('Sorry, could not send the message.');
        msg.removeClass('saving');
    };
    
    var url = '/share/';
    var idList = checked_notes.join(',');
    var params = {"email": email, "obj": 'note', "id": idList};
    post(url, params, success, failure);
};

function shareSelectedNotes() {
    var email = $('#id_email_note').val();
    var links = '';
    var msg = $('#id_msg');

    // User is sharing one or more notes from the note_list_item
    // table body.
    var checked_notes = [];
    $('tbody#note_list_item :checkbox[checked]').each(function() {
        checked_notes.push($(this).val());
    });
        
    if (checked_notes) {
        shareNotesByID(checked_notes, msg, email);
    }
    return false;
};


function deleteNotes(obj, id){
	var links = '';
	var msg = $('#id_msg');
		
	if (id == null) {
		// Get IDs of all notes checked for deletion.
		var checked_notes = [];
		$('tbody#note_list_item :checkbox[checked]').each(function() {
			checked_notes.push($(this).val());
		});
		id = checked_notes.join(",");
	} 
		
	if (id != null && id != '') {
		msg.addClass('deleting');
		msg.html('Deleting Notes');
	
		var success = function(response, status){ 
			msg.html(response); 
			msg.removeClass('deleting');
			loadToolbox('/note');
		};
		var failure = function(t) {
			msg.html('Sorry failed to delete.');
			msg.removeClass('deleting');
		};
		
		var url = '/notes/delete/';
		var params = {"obj":obj, "id":id};
		post(url, params, success, failure);
	}
};


function deleteNote(note_id){
	var ret = confirm('Delete this note?');
	if (ret == true) {
		var msg = $('#id_msg');
		msg.addClass('deleting');
	
		var success = function(response, status){ 
			if (response == "Success.") {
				loadToolbox('/note');
			} else {
				msg.html(response);
			}
			msg.removeClass('deleting');
		};
		var failure = function(t){
			msg.html('Sorry, unable to delete.');
			msg.removeClass('deleting');
		};
		
		var url = '/note/delete/';
		var params = {"note_id": note_id};
		post(url, params, success, failure);
	}
};

function copyNote(note_id){
	var msg = $('#id_msg');

	var success = function(response, status) {
		if (isNaN(response)) {
			msg.html(response);
		} else {
			toolboxNoteID = response;
			msg.html('Note copied.');
		}
		msg.removeClass('saving');
		loadToolbox('/note/',toolboxNoteID);
	};
	var failure = function(t){
		msg.html('Sorry, unable to copy.');
		msg.removeClass('saving');
	};
	
	msg.addClass('saving');
	var url = '/note/copy/';
	var params = {"note_id": note_id};
	post(url, params, success, failure);
};

function postForm(theForm, url, msgSelector, nextURL) {
    var msg = $(msgSelector ? msgSelector : "#non_existent");
    
    var success = function(response, status) {
        msg.html('');
        if (nextURL != null) {
            loadToolbox(nextURL);
        } else {
            // Try to display the response HTML inside the toolbox.
            $('#toolbox').html(response);
        }
    };
    var failure = function(t) {
        msg.html("Sorry, unable to send message.");
    };

    msg.html("Sending...");
    var params = $(theForm).serialize();
    post(url, params, success, failure);
    
    return false; // Try to prevent event propagation.  May not work if user hits return...
};

function postDjangoForm(theForm, url, nextURL) {
    var success = function(response, status) {
        // Does the response contain Django errors?
        var responseDoc = $(response);
        var errorMsgs = $('.errorlist', responseDoc);
        errorMsgs.addClass("visible");
        var hasErrors = (errorMsgs.length > 0);
        if (!hasErrors && (nextURL != null)) {
            loadToolbox(nextURL);
        } else {
            // Try to display the response HTML inside the toolbox.
            $('#toolbox').html(responseDoc);
        }
    };
    var failure = function(t) {
        
    };
    
    var params = $(theForm).serialize();
    post(url, params, success, failure);
    
    return false;
};


//---------------------------------------------------------------------
// Support for Ajaxian login and signup:
//---------------------------------------------------------------------
// XXX FIX THIS -- flaky code depends too much on DOM element IDs.
// Find URLs which, following login/signup, would bring user back
// to the tab they're currently viewing.
function getCurrentURLs(currURL) {
    var nextURL = location.pathname + location.search + location.hash;
    if (nextURL == '/') {
        var currAnchor = $('#toolbox-nav li#current a');
        if (currAnchor.length > 0) {
            var href = currAnchor.attr('href');
            var m = href.match(/^javascript:loadToolbox\((.*)\)/);
            if (m) {
                var fields = m[1].split(",");
                fields[0] = fields[0].replace(/^'(.*)'$/, '$1');
                while (fields.length < 5) {
                    fields.push("");
                }
                nextURL = '/#toolbox,' + fields.join(",");
            }
        }
    }
    var result = {
        'currURL': currURL,
        'nextURL': nextURL ? nextURL : "/"
    };
    // throw new Error("Current URL: " + result.nextURL + " vs. /" + location.hash);
    return result;
};

// Create a success callback for an Ajax login/signup call.
// The call should return a document fragment containing an optional
// failure sentinel.  If the sentinel appears, the document fragment
// should be rendered into responseContainer.  Otherwise the browser
// should load nextURL.
function loginSignupSuccessCB(what, nextURL, responseContainer) {
  var pattern = ('<!-- ' + what + '_FAILED -->');
  var nextPattern = ('<!-- next=\(.*\) -->');
  var expr = new RegExp(pattern);
  var nextExpr = new RegExp(nextPattern);
  var result = function(response, status) {
      // If the response includes an error flag, then the server
      // returned a new login form, with errors embedded.
      // Otherwise it should have returned the next URL.
      if (response.search(expr) >= 0) {
          responseContainer.html(response);
          // Safari workaround:  .errorlist initially is not displayed, so
          // it doesn't shove other form elements around before being
          // moved into a wrapper.
          var errorList = $('.errorlist', responseContainer);
          var zIndex = errorList.css('z-index');
          errorList
           .wrap('<div class="errorlist_wrapper" title="click to close"></div>')
           .before('<div class="errorlist_close">X</div>')
           .addClass('visible');
          $('.errorlist_wrapper')
           .css('z-index', zIndex)
           .click(function() {
                      $(this).css('display', 'none');
                 });
      } else {
          var nextMatch = response.match(nextExpr);
          if (nextMatch != null) {
              nextURL = window.eval("(" + nextMatch[1] + ")");
          }
          
          var newPathname = nextURL.match(/^[^#?]*/)[0];
          var force = (newPathname == location.pathname);
          location.href = nextURL;
          if (force) {
              window.setTimeout(function() {
                  location.reload(true);
              });
          }
      }
  };
  return result;
};

function initSortBar(container, contentURL, sortBy) {
    function getSortKey(col) {
        var colID = col.attr('id');
        var sortKeySig = colID.match(/^sort_by_(.*)/);
        return sortKeySig[1];
    };
    
    function getCurrCol() {
        var result = null;
        var currSort = sortBy.replace(/^-/, '');
        result = $('td.sortcol[id=sort_by_' + currSort + '],td.sortcol[id=sort_by_-' + currSort + ']', container);
        return result;
    };
    
    $('td.sortcol', container).each(function(index) {
        var col = $(this);
        var href = $('a', col);
        href.unbind('click');
        // Requires a full page load to update currSort via templating.
        href.click(function() {
            var sortKey = getSortKey(col);
            var newSortKey = sortKey;
            if (sortKey == sortBy) {
                if (sortKey.slice(0, 1) == '-') {
                    newSortKey = sortKey.slice(1);
                } else {
                    newSortKey = '-' + sortKey;
                }
            }
            loadToolbox(contentURL, '', 1, newSortKey);
            return false;
        });
    });
    // Highlight the current column.
    $('td.sortcol', container).removeClass('current');
    getCurrCol().addClass('current');
};

