/*============================================================================*/
/*  Backpack LIB                                                              */
/*  Version: 0.1                                                              */
/*  Author:  Romuald du Song                                                  */
/*  License: GPL 2.0 see license.txt                                          */
/*============================================================================*/

/*
 * Tag
 */
function Tag(id, name, content) {
  this.id = id;
  this.name = name;
  this.content = content;
}

Tag.prototype.toString = function () {
  var max = 80;
  if (this.content.length > max) {
    return "[id:"+this.id+" name:"+this.name+" content:"+this.content.substring(1,max)+"(...)]";
  } else {
    return "[id:"+this.id+" name:"+this.name+" content:"+this.content+"]";
  }
}

/*
 * Note
 */
function Note(id, title, created_at, content) {
  this.id = id;
  this.title = title;
  this.created_at = created_at;
  this.content = content;
}

Note.prototype.toString = function () {
  var max = 80;
  if (this.content.length > max) {
    return "[id:"+this.id+" title:"+this.title+" created_at:"+this.created_at+" content:"+this.content.substring(1,max)+"(...)]";
  } else {
    return "[id:"+this.id+" title:"+this.title+" created_at:"+this.created_at+" content:"+this.content+"]";
  }
}

/*
 * Item
 */
function Item(page_id, id, list_id, completed, content) {
  this.page_id = page_id;
  this.id = id;
  this.list_id = list_id;
  this.completed = completed;
  this.content = content;
}

Item.prototype.toString = function () {
  var max = 80;
  if (this.content.length > max) {
    return "[id:"+this.id+" page_id:"+this.page_id+" list_id:"+this.list_id+" completed:"+this.completed+" content:"+this.content.substring(1,max)+"(...)]";
  } else {
    return "[id:"+this.id+" page_id:"+this.page_id+" list_id:"+this.list_id+" completed:"+this.completed+" content:"+this.content+"]";
  }
}

Item.prototype.remoteUpdate = function() {
 var api = getConnector();
 return api.updateItem( this.id, this.content, this.page_id);
}

Item.prototype.remoteToggle = function() {
 var api = getConnector();
 return api.toggleItem( this.id, this.page_id);
}

/*
 * Page
 */
function Page(id, title, email_address, description) {
  this.id = id;
  this.title = title;
  this.email_address = email_address;
  this.description = description;

  if (this.email_address == undefined) {
    this.email_address = '';
  }
  if (this.description == undefined) {
    this.description = '';
  }
}

Page.prototype.items = function (itemArray) {
  if (itemArray)
	  this._items = itemArray;
  return this._items;
}

Page.prototype.notes = function (itemArray) {
  if (itemArray)
	  this._notes = itemArray;
  return this._notes;
}

Page.prototype.tags = function (itemArray) {
  if (itemArray)
	  this._tags = itemArray;
  return this._tags;
}

Page.prototype.toString = function () {
  var max = 80;
  if (this.description.length > max) {
    return "[id:"+this.id+" title:"+this.title+" email:"+this.email_address+" description:"+this.description.substring(1,max)+"(...)]";
  } else {
    return "[id:"+this.id+" title:"+this.title+" email:"+this.email_address+" description:"+this.description+"]";
  }
}


/*
 * Api
 */
function Api(userid, token) {
  this.userid = userid;
  this.token = token;
  this.protocole = "http";
  this.current_page_id = undefined;
}

Api.prototype.pageId = function (id) {
  this.current_page_id = id;
}

Api.prototype.toString = function () {
  return "[userid:"+this.userid+"]";
}

Api.prototype.listPages = function () {
  return this.request("pages/all");
}

Api.prototype.createPage = function (title, body) {
	this.request( "pages/new", { page: { title: title, description: body } } );
}

Api.prototype.showPage = function (page_id) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	return this.request( "page/"+page_id );
}

Api.prototype.destroyPage = function (page_id) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	this.request( "page/"+page_id+"/destroy" );
}

Api.prototype.updateTitle = function (title, page_id) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	this.request( "page/"+page_id+"/update_title", { page: { title: title } } );
}

Api.prototype.update_body = function (body, page_id ) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	this.request( "page/"+page_id+"/update_body", { page: { description: body } } );
}

Api.prototype.link_page = function (linked_page_id, page_id ) {
	/*
	if (page_id == undefined)
	  page_id = this.current_page_id;
	this.request( "page/"+page_id+"/link", "linked_page_id" => linked_page_id );
	*/
}

Api.prototype.unlink_page = function (linked_page_id, page_id ) {
	/*
	if (page_id == undefined)
	  page_id = this.current_page_id;
	this.request( "page/"+page_id+"/unlink", "linked_page_id" => linked_page_id );
	*/
}

Api.prototype.share_page = function (email_addresses, public_page, page_id ) {
	/*
	if (page_id == undefined)
	  page_id = this.current_page_id;
	parameters = { "email_addresses" => email_addresses }
	parameters = parameters.merge({ "page" => { "public" => public_page ? "1" : "0" }}) unless public_page.nil?
	this.request( "page/#{page_id}/share", parameters );
	*/
}

Api.prototype.listItems = function (page_id ) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	this.request("page/"+page_id+"/items/list");
}

Api.prototype.createItem = function (content, page_id ) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	return this.request("page/"+page_id+"/items/add", [ 'item', [ 'content', content ] ]);
}

Api.prototype.updateItem = function (item_id, content, page_id ) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	return this.request("page/"+page_id+"/items/update/"+item_id, [ 'item', [ 'content', content ] ]);
}

Api.prototype.destroyItem = function (item_id, page_id ) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	return this.request("page/"+page_id+"/items/destroy/"+item_id);
}

Api.prototype.toggleItem = function (item_id, page_id ) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	return this.request("page/"+page_id+"/items/toggle/"+item_id);
}

Api.prototype.moveItem = function (item_id, direction, page_id ) {
	if (page_id == undefined)
	  page_id = this.current_page_id;
	return this.request("page/"+page_id+"/items/move/"+item_id, [ 'direction', "move_"+direction ]);
}

/*
 * Return an array of Item objects
 */
Api.prototype.getItemsOnPage = function (page_id) {
  var xml = this.listItems(page_id);
  var itemsArray = new Array();

  try
  {
    if ( xml.match( "response success=\"true\"" ) )
    {
      doc = XMLDOM.parse( xml );

        var itemsNodes = doc.evaluate("//items/item");

        for (var k =0; k < itemsNodes.length; k++) {
          var item = itemsNodes.item(k);
          var _id = item.evaluate("string(@id)");
          var _list_id = item.evaluate("string(@list_id)");
          var _completed = item.evaluate("string(@completed)");
          var _content = item.evaluate("string(.)");
	  var item = new Item(page_id, _id, _list_id, _completed, _content);
	  itemsArray[itemsArray.length] = item;
	}
    }
  }
  catch ( e )
  {
    alert( "There was an error parsing the items data.  It's likely that there is a problem with the information that was retreived.\n\nThe error returned was \"" + e + ".\"" );
  }
  return itemsArray;
}

Api.prototype.getShowPage = function (page_id) {
  var xml = this.showPage(page_id);
  var page = undefined;

  try
  {
    if ( xml.match( "response success=\"true\"" ) )
    {
      doc = XMLDOM.parse( xml );
      var resultNodes = doc.evaluate( "//page" );

      for (var i =0; i < resultNodes.length; i++) {
        var n = resultNodes.item(i);
        var _title = n.evaluate("string(@title)");
        var _pid = n.evaluate("string(@id)");
        var _email = n.evaluate("string(@email_address)");
        var _description = n.evaluate("string(description)");
	page = new Page(_pid, _title, _email, _description);


        var itemsNodes = n.evaluate("items/item");
	var itemsArray = new Array();

        for (var k =0; k < itemsNodes.length; k++) {
          var item = itemsNodes.item(k);
          var _item_id = item.evaluate("string(@id)");
          var _list_id = item.evaluate("string(@list_id)");
          var _completed = item.evaluate("string(@completed)");
          var _content = item.evaluate("string(.)");
	  var item = new Item(page_id, _item_id, _list_id, _completed, _content);
	  itemsArray[itemsArray.length] = item;
	}
	page.items(itemsArray);

        var notesNodes = n.evaluate("notes/note");
	var notesArray = new Array();
        for (var k =0; k < notesNodes.length; k++) {
          var item = notesNodes.item(k);
          var _note_id = item.evaluate("string(@id)");
          var _title = item.evaluate("string(@title)");
          var _created_at = item.evaluate("string(@created_at)");
          var _content = item.evaluate("string(.)");
	  var note = new Note(_note_id, _title, _created_at, _content);
	  notesArray[notesArray.length] = item;
	}
	page.notes(notesArray);

        var tagsNodes = n.evaluate("tags/tag");
	var tagsArray = new Array();
        for (var k =0; k < tagsNodes.length; k++) {
          var item = tagsNodes.item(k);
          var _tag_id = item.evaluate("string(@id)");
          var _name = item.evaluate("string(@name)");
          var _content = item.evaluate("string(.)");
	  var tag = new Tag(_tag_id, _name, _content);
	  tagsArray[tagsArray.length] = item;
	}
	page.tags(tagsArray);

      }

    }
  }
  catch ( e )
  {
    alert( "There was an error parsing the data on current page.  It's likely that there is a problem with the information that was retreived.\n\nThe error returned was \"" + e + ".\"" );
  }
  return page;
}

/*
 * Return an array of Page objects
 */
Api.prototype.getListPages = function () {
  var xml = this.listPages();
  var pages = new Array();

  try
  {
    if ( xml.match( "response success=\"true\"" ) )
    {
      doc = XMLDOM.parse( xml );

      var resultNodes = doc.evaluate( "//page" );
      for (var i =0; i < resultNodes.length; i++) {
        var n = resultNodes.item(i);
        var _title = n.evaluate("string(@title)");
        var _id = n.evaluate("string(@id)");
	var p = new Page(_id, _title);
	pages[pages.length] = p;
      }
    }
  }
  catch ( e )
  {
    alert( "There was an error parsing the pages data.  It's likely that there is a problem with the information that was retreived.\n\nThe error returned was \"" + e + ".\"" );
  }
  return pages;
}

Api.prototype._makeUrl = function (path) {
  return this.protocole+"://"+this.userid+".backpackit.com"+"/ws/"+path;
}

Api.prototype.toXML = function (data) {
  var t=data[0];
  var st="<"+t+">";
  var et="</"+t+">";
  if (typeof(data[1]) == "object") {
    return st+this.toXML(data[1])+et;
  } else {
    return  st+this.escapeXML(data[1])+et;
  }
}


Api.prototype.request = function (path, parameters) {
  var url = new URL();

  var theURL = this._makeUrl(path);
  var data= "<request><token>"+this.token+"</token>";
  if (parameters) {
    var xml = this.toXML(parameters);
    data = data + xml;
  }
  data = data + "</request>";

  url.setRequestHeader("X-POST_DATA_FORMAT", 'xml');
  url.postData= data;
  url.location = theURL;


  url.fetch();
  if (url.response == "200") {
	  return url.result;
  } else {
	  connected = false;
	  return 0;
  }
}

Api.prototype.escapeXML = function(data) {
  var _xml = data.replace(/&/,"&amp;");
  _xml = _xml.replace(/</,"&lt;");
  _xml = _xml.replace(/</,"&gt;");
  return _xml;
}

