// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2009
// http://flock.com
//
// This file may be used under the terms of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL

// Sample AtomEntry:
// entry = {
//   id: "urn:example.org:reilly:1",
//   link: "http://example.org/reilly/2003/02/05#My_First_Entry"
//   title: "My First Entry",
//   summary: "A very boring entry...",
//   categories: ["one", "two"],
//   author_name: "Bob B. Bobbington",
//   author_url: "http://bob.name/",
//   issued: new Date(),
//   created: new Date(),
//   modified: new Date(),
//   content: "<p>The complete entry....<br/>blablabla...</p>",
// }
//
// /!\ Some attributes are optionals, some are required according to the call that is done.


const FLOCK_GENERATOR = "Flock Alpha";


function flockAtomPost(aBlogListener, aPostURI, aAtomEntry, auth) {
  // Make sure we have the required fields
  if (!aAtomEntry.title)
    aAtomEntry.title = "";
  if (!aAtomEntry.issued)
    aAtomEntry.issued = ""; // An empty 'issued' means now (in the timezone of the server)
  var entry = <entry/>;
  entry.@xmlns = 'http://www.w3.org/2005/Atom';
  entry.generator = FLOCK_GENERATOR;
  entry.generator.@url = 'http://flock.com';
  entry.title = aAtomEntry.title;
  entry.title.@mode = 'escaped';
  if (aAtomEntry.summary)
    entry.summary = aAtomEntry.summary;
  if (aAtomEntry.content) {
    entry.content = aAtomEntry.content;
    entry.content.@mode = 'escaped';
  }
  if (aAtomEntry.created) entry.created = aAtomEntry.created;
  if (aAtomEntry.author_name) {
    entry.author.name = aAtomEntry.author_name;
    if (aAtomEntry.author_url)
      entry.author.url = aAtomEntry.author_url;
  }
  if (aAtomEntry.categories) {
    for (i in aAtomEntry.categories) {
      entry.category[i] = "";
      entry.category[i].@term = aAtomEntry.categories[i];
      entry.category[i].@scheme = "http://www.blogger.com/atom/ns#";
    }
  }

  flockAtomDoRequest(aBlogListener, aPostURI, "POST", entry, auth);
}


function flockAtomEdit(aBlogListener, aEditURI, aAtomEntry, auth) { 
  var entry = <entry/>;
  entry.@xmlns = 'http://www.w3.org/2005/Atom';
  entry.generator = FLOCK_GENERATOR;
  entry.generator.@url = 'http://flock.com';
  entry.id = aAtomEntry.id;
  entry.title = aAtomEntry.title;
  entry.title.@mode = 'escaped';
  entry.issued = aAtomEntry.issued;
  if (aAtomEntry.summary)
    entry.summary = aAtomEntry.summary;
  if (aAtomEntry.content) {
    entry.content = aAtomEntry.content;
    entry.content.@mode = 'escaped';
  }
  if (aAtomEntry.created) entry.created = aAtomEntry.created;
  if (aAtomEntry.author_name) {
    entry.author.name = aAtomEntry.author_name;
    if (aAtomEntry.author_url)
      entry.author.url = aAtomEntry.author_url;
  }
  if (aAtomEntry.categories) {
    for (i in aAtomEntry.categories) {
      entry.category[i] = "";
      entry.category[i].@term = aAtomEntry.categories[i];
      entry.category[i].@scheme = "http://www.blogger.com/atom/ns#";
    }
  }

  flockAtomDoRequest(aBlogListener, aEditURI, "PUT", entry, auth);
}


function flockAtomDelete(aBlogListener, aEditURI, auth) {
  flockAtomDoRequest(aBlogListener, aEditURI, "DELETE", null, auth);
}


// Private methods

function flockAtomParseEntry(aEntryDom) {
  // Only get the information we really care about
  var entry = new Object();

  var entryTag = aEntryDom.getElementsByTagName("entry")[0];
  entry.id = entryTag.getElementsByTagName("id")[0].nodeValue;
  var linkTags = entryTag.getElementsByTagName("link");
  for (i = 0; i < linkTags.length; i++) {
    var link = linkTags[i];
    if (link.getAttribute("rel").match(/edit/)) {
      entry.editURI = link.getAttribute("href");
    }
    else if (link.getAttribute("rel").match(/alternate/)) {
      entry.link = link.getAttribute("href");
    }
  }

  return entry;
}

function flockAtomParsePosts(aBlogListener, inst) {
  var dom = inst._req.responseXML;
  debug("Status: "+inst._req.status);
  debug(inst._req.responseText);
  switch (inst._req.status) {
    case 200: // No server should ever return a 200 after a POST or a PUT,
              // but they do it anyway
      if (!dom) { // Livejournal hackage: they return an HTML page instead of an Atom Entry
        if(inst._req.responseText.match(/OK/)) {
          aBlogListener.onResult({});
          return;
        }
        else {
          var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"].getService(Components.interfaces.nsILocaleService);
          var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
          var stringBundle = stringBundleService.createBundle("chrome://flock/locale/blog/blog.properties", localeService.getApplicationLocale());

          var string = stringBundle.GetStringFromName("flock.blog.atom.error");

          var fault =  {
            faultString: string
          };
          aBlogListener.onFault(fault);
          return;
        }
      }
      else {
        // OK, let's consider that it worked...
        aBlogListener.onResult(new Object());
        return;
       }
    case 201: // The server returned the editURI + the entry
      var entry = flockAtomParseEntry (dom);
      aBlogListener.onResult(entry);
      break;
    case 303: // The server returned only the editURI
      var entry = new Object();
      entry.editURI = inst._req.getResponseHeader('Location');
      // TODO: do a GET to get the full entry
      aBlogListener.onResult(entry);
      break;
    case 400: // Invalid request
      var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"].getService(Components.interfaces.nsILocaleService);
      var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
      var stringBundle = stringBundleService.createBundle("chrome://flock/locale/blog/blog.properties", localeService.getApplicationLocale());

      var string = stringBundle.GetStringFromName("flock.blog.atom.error");

      var error = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
      error.serviceErrorCode = 400;
      error.serviceErrorString = string;
      aBlogListener.onFault(error);
      break;
    case 401: // Token disabled/expired
      var error = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
      error.serviceErrorCode = 401;
      error.serviceErrorString = inst._req.responseText;
      aBlogListener.onFault(error);
      break;
    case 403: // Account disabled/expired
      var error = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
      error.serviceErrorCode = 403;
      error.serviceErrorString = inst._req.responseText;
      aBlogListener.onFault(error);
      break;
    case 500: // Server internal error
      var error = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
      error.serviceErrorCode = 500;
      error.serviceErrorString = inst._req.responseText;
      aBlogListener.onError(error);
      break;
    default: // The server should not return any other code
      break;
  }
}


function flockAtomDoRequest(aBlogListener, url, method, entry, auth) {
  var inst = this;
  this._req = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Components.interfaces.nsIXMLHttpRequest);
  this._req.onreadystatechange = function (aEvt) {
    if(inst._req.readyState == 4) {
      var status = inst._req.status;
      dump("STATUS = " + status + "\n");
      switch (status) {
        case 200: 
        case 201:
        case 205:
          flockAtomParsePosts(aBlogListener, inst);
          break;
        case 401: // Token disabled/expired/invalid
        case 403: // Account disabled/expired/invalid
          var error = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
          error.serviceErrorCode = status;
          error.serviceErrorString = inst._req.responseText;
          aBlogListener.onFault(error);
          break;
        case 0: // connection lost
        case 500: // Server internal error
          var error = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
          error.serviceErrorCode = status;
          error.serviceErrorString = inst._req.responseText;
          aBlogListener.onError(error);
          break;
        default: // The server should not return any other code
          break;
      }
    }
  };
  if (auth instanceof Array) { // username/password
    //dump("Launch query with "+auth[0]+" "+auth[1]+"\n");
    rval = this._req.open(method, url, true, auth[0], auth[1]);
  }
  else { // Google auth
    rval = this._req.open(method, url, true);
    this._req.setRequestHeader("Authorization", "GoogleLogin auth="+auth);
  }
  this._req.setRequestHeader("Content-Type", "application/atom+xml");
  //dump(">>>>>>>>>> Atom API: FLOCK TO SERVER\n");
  //dump("\nSENDING\n" + entry.toXMLString());
  //dump("\nTO\n" + method + " @ " + url + "\n");
  rval = this._req.send('<?xml version="1.0" encoding="utf-8"?>\n'+entry.toXMLString ()); 
}
