// not the userscript version
// because the script originated in greasemonkey, there are no synchrounous ajax calls, only ones with continuations

// Add jQuery
var GM_JQ = document.createElement('script');
GM_JQ.src = 'http://tirno.com/jquery-autocomplete.js';
GM_JQ.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(GM_JQ);

var GM_JQCSS = document.createElement('link');
GM_JQCSS.href = 'http://tirno.com/jqac.css';
GM_JQCSS.type = 'text/css';
GM_JQCSS.rel = "stylesheet";
document.getElementsByTagName('head')[0].appendChild(GM_JQCSS);


// Check if jQuery's loaded
function GM_wait() {
  if(typeof window.jQuery == 'undefined') { window.setTimeout(GM_wait,100); }
  else {letsJQuery();  }
}

// GM_xmlhttpRequest({
//    method:"GET",
//    url:"http://localhost:8090/ping",
//    onload:function(response) {
//      PostTagger.baseurl = "http://localhost:8090/";
//      PostTagger.test = true;
//    }
//  });

GM_wait();

PostTagger.username = ""; // access anywhere
PostTagger.title = "";
PostTagger.suggestions = [];
 PostTagger.baseurl = "http://tagtradzone.appspot.com/";
 PostTagger.test = false;
//     PostTagger.baseurl = "http://localhost:8090/";
//     PostTagger.test = true;

/* get username
   get the tags for this page
   initialise all the ui elements
   by creating a PostTagger for each of them
*/
function letsJQuery() {

  window.setTimeout(function() {
      start_tagger()
  }, 200);
  //GM_log("give a little time for baseurl to be set");

}

function start_tagger() {

  //GM_log("starting with basurl: " +PostTagger.baseurl);

  var userlogout = $("a.mainmenu:last").text();
  if (userlogout == "Connexion") {
    //GM_log("User not logged in");
    return;
  }
  PostTagger.username = /\[\s(.*)\s\]/(userlogout)[1];
 
  if (PostTagger.username != "Tirno" && PostTagger.username != "Ekks-O") {
    return;
  }
  //alert("Username: " + PostTagger.username);
  PostTagger.title = $("a.maintitle").text();
  //GM_log("Title: " + PostTagger.title);

  var postdetails = $("span.postdetails"); 
  var tds = postdetails.filter(":odd").parent();
  var authors = postdetails.filter(":even").parent().map(getAuthor).get();
  var ids = tds.map(getPostId).get();

  getAllTags(function(val) {allTagsGot(val,tds,ids, authors)});
}
// continuation will resume here
function allTagsGot(suggestions,tds,ids, authors) {
  PostTagger.suggestions = suggestions;
  getTagsFor(ids, function(val) {tagsForGot(val,tds,ids, authors)});
}
// continuation will resume here
function tagsForGot(tagsforids,tds,ids, authors) {
  tds.each(function(i) {
      var td = $(this).nextAll("td:first"); // td containing the buttons
      var tr = $(this).parent().nextAll("tr:first").children("td"); // tr between post header and post
      var div = tr.prepend("<div></div>").children(":first");
      var id = ids[i];
      var author = authors[i];
      new PostTagger(id,author,div,td,tagsforids[id]);
    });
  //GM_log("Added tagging functionalities to "+ tds.length +" posts.");
};

PostTagger.taggers = new Array();

function PostTagger(postid, author,uiparent,buttonparent,tags) {
  this.postid = postid;
  this.author = author;
  this.tags = [];
  this.ui = this.createTagInterface(uiparent);
  this.button = this.createTagLink(buttonparent);
  this.isvisible = true;

  this.addTags(tags);

  if (this.tags.length == 0) { // make invisible if no tags yet
    this.toggleUI(false);
  }

  PostTagger.taggers.push(this); // prevent garbage collection? or is it not necessary?
};

PostTagger.prototype.toggleUI = function(animate) {
  speed = animate ? 250 : 0;
  if (this.isvisible) {
    this.isvisible=false;
    $(this.ui).hide(speed);
  } else {
    this.isvisible=true;
    $(this.ui).show(speed);
  }
};

PostTagger.prototype.createTagLink = function(parent) {
  var link = $("<a>tagger</a>");
  link.data("tagger",this); // needed for callbacks
  link.addClass("taggerlink");
  if (PostTagger.test) {
    link.addClass("test");
  }
  link.click(function() {
      $(this).data("tagger").toggleUI(true);
    });
  $(parent).prepend(link);
  return link;
};

PostTagger.prototype.createTagInterface = function(parent) {
  parent = $(parent);

  var tags = $("<span>pas encore de tags</span>");
  tags.addClass("taggertags").addClass("taggertext");
  parent.append(tags);

  var input = $("<input type='text'></input>");
  input.autocomplete({ get : get_tag_suggs,
	multi: true,
	minchars: 1,
	delay: 100,
	cache: false});
  
  // get the keydown handler bound by autocomplete 
  var jqac_keydown = input.data("events")["keydown"];
  for (var k in jqac_keydown) {
    jqac_keydown = jqac_keydown[k];
    break; // only take the first one
  }
  input.unbind("keydown");

  // bind our own handler which is calls the autocomplete handler
  // and assigns the tags when return is pressed
  input.data("tagger",this); // needed for callbacks
  input.bind("keydown",function(ev){
      if (jqac_keydown.apply(this,[ev])) {
	  switch(ev.which){
	  case 13:
	    var input = $(this);
	    var tagger = input.data("tagger");
	    var id = tagger.postid;
	    var author = tagger.author;
	    var tagnames = input.attr("value");
	    input.attr("value","");
	    input.trigger("keyup"); // clear the selection list
	    setTagsFor(id, author, PostTagger.title, PostTagger.username, tagnames, 
		       function(tagnames) {
			 tagger.addTags(tagnames);
			 for (var i=0; i<tagnames.length; i++) {
			   addToSuggestions(tagnames[i]);
			 }
		       });
	  }
	  return true;
      }
      return false;
  });

  var label = $("<span>ajouter:</span>").addClass("taggertext").addClass("taggeradd");
  parent.append(label);
  parent.append(input);
  return parent;
};

PostTagger.prototype.addTags = function(tagnames) {
  for (var i in tagnames) {
    this.addTag(tagnames[i]);
  }
}

PostTagger.prototype.addTag = function(tagname) {
  // create the tag html
  var tag = $("<a>"+tagname+"</a>").attr("href",getTagUrl(tagname));

  // get insertion place
  var span = $(this.ui).children(":first");

  if (this.tags.length == 0) {
    span.text("tags: "); // first tag
  } else {
    span.append(", "); // subsequent tags
  }
  span.append(tag);
  this.tags.push(tagname);
}

function get_tag_suggs(v){ 
   var a=[];
   var s=PostTagger.suggestions;
   myRegExp = new RegExp("^"+v, "i")  
   for(var category in s) {
     var tags = s[category];
     var matchcategory = myRegExp.test(category);
     for (var i=0; i<tags.length; i++) {
       if (matchcategory) {
	 a.push({id:category+i, value:tags[i], info:category})
       } else if (myRegExp.test(tags[i])) {
	 a.push({id:category+i, value:tags[i]});
       }
     }
   }
   return a;
}

function getTagUrl(tagname) {
  return "http://tagtradzone.appspot.com/search?q="+tagname;
}

function getPostId() {
  // link to original post is in the first child of the TD
  // looks like "viewtopic.php?p=120178#120178"
  // get the part between = and #
  var href = $(this).children(":first").attr("href");
  return /=(\d*)#/(href)[1]; 
};

function getAuthor() {
  return $(this).children(":first").find("b a").text();
}

/** get all the tags for the specified ids
 *
 * @param ids an array of ids such as ["12355","23423"] etc.
 * @return tags for each id such as {"12355":[], "23423":["tag1","tag2"]}
*/
function getTagsFor(ids, cont) { // this call will be synchronous (simulated by continuation)
  //GM_log("getTagsFor: "+ids.join(","));

  //GM_log("sending ajax for get tags")
  $.getJSON(PostTagger.baseurl+"json/gettags?jsonp=?",{ids: ids.join(",")},cont);
//   $.ajax({
//     type: "GET",
// 	url: PostTagger.baseurl+"json/gettags",
// 	data: {ids: ids.join(",")},
// 	dataType: "text", // don't mention it's json otherwise jquery looks at the url and thinks "baaah"
// 	success: function(responsestring) {
// 	//GM_log("response: "+ responsestring);
// 	eval("var tagarray =("+responsestring+")");
// 	//GM_log("found  tags"+tagarray);
// 	     cont(tagarray);
//       }
//     });
}; 

/** Set the tags for the specified id
 *
 * @param id String of the id such as "12355"
 * @param user String of the user such as "Tirno"
 * @param tags String of tags such as "tag1, tag2, tag3"
 * @param cont Continuation function to be called on success with parameter: an array of assigned tags 
 * @return void 
 */
function setTagsFor(id, author, title, user, tags, cont) { // this call will be async.
  //GM_log("setTags: "+[id,author, title, user,tags,cont].join(", "));
  if (!tags) {
    //GM_log("Tags is empty, NOP");
    return;
  }
  // fill in ajax call here, return tags that have been assigned
  //tagarray = tags.split(/,\s*/);
  //GM_log("sending ajax to: " + PostTagger.baseurl+"json/addtags");

  $.getJSON(PostTagger.baseurl+"json/addtags?jsonp=?", {id:id, author:author,title:title,user:user,tags:tags}, cont);


//   $.ajax({ 
//     type: "POST",
// 	url: PostTagger.baseurl+"json/addtags",
// 	data: {id:id, author:author,title:title,user:user,tags:tags},
// 	dataType: "text", // don't mention it's json otherwise jquery looks at the url and thinks "baaah"
// 	success: function(responsestring) {
// 	//GM_log("response:" + responsestring);
// 	eval("var tagarray =("+responsestring+")");
// 	//GM_log("tagarray"+tagarray);
// 	     cont(tagarray);
//       }
//     });



  // call continuation function with the assigned tag array
  // TODO add in display of tags that were not assigned for whatever reason.
  // TODO add in "busy indicator"
  //cont(tagarray);
};

function getAllTags(cont) { // do this with remote call for now (while in greasemonkey). simulated synchronous
  var tags = {"instruments":["cornemuse","flute", "violon", "accordeon", "clarinette", "concertina"],
	      "danses":     ["mazurka","bourrée","polka","cercle circassien","valse","jig","fandango"],
	      "festivals":  ["damada","gennetines","p'tit festival","boombal"],
	      "groupes":    ["komred","bardane","tradirrationnel"],
	      "":           ["idée","opinion","explication","viellux","danse","enseignement",
		  "partition","mode","solfege"]
  };
  cont(tags);
};

/** add the array of tags to PostTagger.suggestions 
 * Performs check to see if they are already included
 * TODO perform check serverside?
 */
function addToSuggestions(newtag) {
  var s=PostTagger.suggestions;
  for(var category in s) {
    var tags = s[category];
    for (var i=0; i<tags.length; i++) {
      if (tags[i]==newtag) return;
    }
  }
  PostTagger.suggestions[""].push(newtag);
}












