/* Copyright (c) 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Sample code for Blogger's JavaScript client library. 
 * Provides an embeded blog post editor which grabs the title and location
 * of the current page for promotion on a user's blog.
 * @author api.jscudder@gmail.com (Jeffrey Scudder)
 */

// Load the Google data Blogger JavaScript library.
google.load('gdata', '1.x');
google.setOnLoadCallback(addEditorToPage);

// Global object to hold constants and "global" variables.
var blogThis = {
  // URL constants.
  BLOG_LIST_URL:    'http://www.blogger.com/feeds/default/blogs',
  AUTH_URL:         'http://www.blogger.com/feeds',
  // Document element ID constants.
  SAMPLE_CONTAINER: 'blog_this',
  POST_BODY_INPUT:  'blog_post_body',
  EDITOR_DIV:       'blog_this_div',
  LOGIN_BUTTON:     'login_button',
  BLOG_SELECTOR:    'available_blogs',
  TITLE_INPUT:      'blog_post_title',
  TAGS_INPUT:       'blog_post_tags',
  RESULT_DIV:       'blog_this'
};

/**
 * Simple error handler which displays the error in an alert box.
 * @param {Object} e An error passed in from the google.gdata.service 
 *     object when the HTTP call failed. 
 */
function handleError(e) {
  var statusDiv = document.getElementById(blogThis.RESULT_DIV);
  statusDiv.appendChild(document.createTextNode('Error: ' + (e.cause ? e.cause.statusText : e.message)));
  statusDiv.appendChild(document.createElement('br'));
};
function blogger_service_error_handler(e) {
  $('blog_this').innerHTML = document.getElementById('blogger_unsupported_browser').innerHTML;
}

/**
 * Performs HTML escapes on special characters like double quotes, 
 * less-than, greater-than, and the ampersand. This function is used
 * on the page title to ensure that special characters do not lead to
 * invalid HTML when it is included in the atom:content.
 * I recommend using something like this on any text that you want
 * to be treated as plaintext within HTML content. 
 * @param {String} inputString The string which will be scrubbed.
 * @return {String} The input string with special characters replaced
 *     by their HTML-safe equivalents.
 */
function htmlEscape(inputString) {
  return inputString.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
};

/**
 * Adds the HTML for the login and blog post editor to the sample 
 * container div. It also populates the contents of the blog post edit form
 * with a link to the current page. The current page's title is used as the 
 * anchor text.
 */
function addEditorToPage() {
  // Create the Blogger client object which talks to the blogger servers.
  google.gdata.client.init(blogger_service_error_handler);
  blogThis.service = new google.gdata.blogger.BloggerService('GoogleInc-blogThisEmbeddedEditor-1');

  determineEditorVisibility();
};

/**
 * Populates the contents of the blog post edit form with a link to the
 * current page. The current page's title is used as the anchor text.
 */
function initializeBlogPostInput() {
  // Create the Blogger client object which talks to the blogger servers.
  blogThis.service = new google.gdata.blogger.BloggerService('GoogleInc-blogThisEmbeddedEditor-1');

  determineEditorVisibility();
};

/**
 * Makes the blog post editor div visible if the user is authenticated. If
 * the user is not authenticated with Blogger, the editor div is hidden
 * and the login button is made visible.
 */
function determineEditorVisibility() {
  var blogThisDiv = document.getElementById(blogThis.EDITOR_DIV);
  var loginButton = document.getElementById(blogThis.LOGIN_BUTTON);
  if (google.accounts.user.checkLogin(blogThis.AUTH_URL) && (blogThisDiv != null)) {
    // If the user is logged in, show the blog editor.
    blogThisDiv.show();
    loginButton.hide();
    // Request the feed to populate the editor's blog selection menu.
    blogThis.service.getBlogFeed(blogThis.BLOG_LIST_URL, receiveBlogList, handleError);

    $('facebook_container').hide();
    $('myspace_container').hide();
    $('blogger_container').show();
    $('msnspaces_container').hide();
    $('sendurl_container').hide();
    $('embed_container').hide();
  } else {
    // The user cannot get a list of blogs, so display the login button.
    if (blogThisDiv != null) {
      blogThisDiv.hide();
      loginButton.show();
    }
  }
};

/**
 * Requests an AuthSub token for interaction with the Calendar service.
 */
function blogger_login() {
  var token = google.accounts.user.login(blogThis.AUTH_URL);
  determineEditorVisibility();
};

/**
 * Creates options in the blog editor's drop down blog selector box.
 * This method receives the results of a query for a list of the current
 * viewer's blogs. 
 * @param {Object} blogList An object containing a 
 *     google.gdata.blogger.BlogFeed. 
 */
function receiveBlogList(blogList) {
  // Clear any existing options from the blog selector.
  var selector = document.getElementById(blogThis.BLOG_SELECTOR);
  selector.innerHTML = '';
  // Find the titles and post links for each blog and populate the blog select options.
  var numBlogs = blogList.feed.getEntries().length;
  var newOption;
  for (var i = 0, entry; entry = blogList.feed.getEntries()[i]; ++i) {
    newOption = document.createElement('option');
    newOption.value = entry.getEntryPostLink().href;
    newOption.appendChild(document.createTextNode(entry.getTitle().getText()));
    // Add this as an option to the blog selector.
    selector.appendChild(newOption);
  }

  // No blogs?
  if (document.getElementById(blogThis.BLOG_SELECTOR).innerHTML == '') {
    blogger_service_error_handler();
  }

};

/**
 * Revokes the authentication token for this application.
 * The editor div is then hidden and the login button is displayed.
 */
function blogger_logout() {
  google.accounts.user.logout();
  // Hide the editor div and make the login button visible.
  var blogThisDiv = $(blogThis.EDITOR_DIV).hide();
  var loginButton = $(blogThis.LOGIN_BUTTON).show();
};

/**
 * Reads the contents of the blog post editor and sends it to the Blogger
 * servers as a new blog post.
 */
function insertBlogEntry() {
  // Find the target blog and the post URL.
  var blogSelector = $(blogThis.BLOG_SELECTOR);
  var targetUrl = blogSelector.options[blogSelector.selectedIndex].value;
  // Create event.
  var blogPost = new google.gdata.blogger.BlogPostEntry();
  // Add title - from the input field.
  var title = document.getElementById(blogThis.TITLE_INPUT).value;
  blogPost.setTitle(google.gdata.Text.create(title));
  // Get the body from the input field.
  var body = $(blogThis.POST_BODY_INPUT).value;
  // Set the content to be the body of the input form and tell the server to interpret it as html.
  blogPost.setContent(google.gdata.Text.create(body, 'html'));
  // Read the tags from the input form and add them as categories to the blog post entry.
  var tags = $(blogThis.TAGS_INPUT).value;
  var tagList = tags.split(',');
  for (var i = 0, tag; tag = tagList[i]; ++i) {
    blogPost.addCategory(new google.gdata.Category(
        {'scheme':'http://www.blogger.com/atom/ns#', 
         // Remove leading and trailing whitespace from the tag text.
         // If the tag begins or ends with whitespace, the Blogger server 
         // will remove the whitespace but send back 2 category elements,
         // one with the original term, and another with the stripped term.
         'term':tag.replace(/^\s+/g, '').replace(/\s+$/g, '')}));
  }
  blogThis.service.insertEntry(targetUrl, blogPost, handlePostSuccess, handleError);
};

/**
 * Displays the contents of the new blog post after the Blogger server 
 * responds to the POST request.
 * @param {Object} newBlogPost An object containing the 
 *     google.gdata.blogger.BlogPostEntry sent back from the server.
 */
function handlePostSuccess(newBlogPost) {
  // Get the div which displays the posted blog entries.
  var resultDiv = $(blogThis.RESULT_DIV);
  resultDiv.innerHTML = $('blogger_success').innerHTML;
};
