/**
 * Class: BrandFeed
 */
var BrandFeed = function(domContainer, brand, max_entries, updateCallback){
 
  
  this.$domContainer = domContainer;
  this.$infoContainer;
  this.$itemContainer;
  
  this.updateCallback = updateCallback
  
  this.brand = brand;
  this.max_entries = max_entries || 10 ;

  this.new_item_queue;
  this.$queue_length_html;
  
  this.queueInterval;
  this.queueFrequency = 3000 + Math.floor(Math.random() * 2000);
  this.queueRunning = false;
  
  this.pullInterval;
  this.pullFrequency = 60000 + Math.floor(Math.random() * 20000);
  
  this.updateTimestampInterval;
  this.updateTimestampFrequency = 60000;
  
  this.paused = false;
  this.$pause_html;
  
  this.all_items = new Array();
  
  /**
   * Start 'er up
   */
  this.init = function(){
	var self = this;
	
	this.jsonCallbackFunctionName = '_callbackJSONP_' + this.brand.replace(/ /g,"_");
	window[this.jsonCallbackFunctionName] = function(json) {
		//console.log("Complete: " + json.items[0].title);
		self.handleResponse(json);
	};
	
  	// Create the item and info headers
  	this.createDomContainers();
	
	// Setup new item queue
	this.new_item_queue = new BrandFeedQueue();
	
  	this.pullFeed();
	
	this.pullInterval = setInterval( function(){ self.pullFeed(); }, this.pullFrequency);
	this.queueInterval = setInterval( function(){ self.runQueue(); }, this.queueFrequency);
	this.updateTimestampInterval = setInterval( function(){ self.updateTimestamp(); }, this.updateTimestampFrequency);
	
    // add the pause events
    this.$domContainer.mouseover(function(){self.pause(true);});
    this.$domContainer.mouseout(function(){self.pause(false);});
  }

  this.createDomContainers = function () {
  	this.$domContainer.addClass("brand_feed");
	
	//this.$brandTitle = $(document.createElement('div')).addClass("brand_title");
  	this.$infoContainer = $(document.createElement('div')).addClass("info_container");
    this.$itemContainer = $(document.createElement('div')).addClass("item_container");
	
	//this.$domContainer.append(this.$brandTitle);
	this.$domContainer.append(this.$infoContainer);
	this.$domContainer.append(this.$itemContainer);
	
	//this.$brandName = $(document.createElement('span')).addClass("brand_name");
	//this.$brandName.text(this.brand);
	//this.$brandTitle.text("Brand: ");
	//this.$brandTitle.append(this.$brandName);
	
	this.$queue_length_html = $(document.createElement('span')).addClass("queue_length");
	this.$queue_length_html.text("New Items: Loading...");
	this.$pause_html = $(document.createElement('span')).addClass("paused");
	
	this.$infoContainer.append(this.$queue_length_html);
	this.$infoContainer.append(this.$pause_html);
  }
  
  
  this.pause = function(paused){
    this.paused = paused;
    if (this.paused) {
      this.$pause_html.text("Paused");
    }
    else {
      this.$pause_html.text("");
    }
  }
  
  /**
   * Initiate the pull of the feed
   */
  this.pullFeed = function(){
  	this.$queue_length_html.text("New Items: Loading...");
    var self = this;
	
	/*
    $.getJSON(
	    "http://blackfriday.gershoni.com/bf_feed_jsonp/?brand=" + this.brand + "&count=" + this.max_entries + "&jsoncallback=?",
        function(json){
			self.handleResponse(json);
		}
	);
	*/
	

//	$.ajax({ url: "http://blackfriday.gershoni.com/bf_feed_jsonp/?brand=" + this.brand + "&count=" + this.max_entries + "&jsoncallback=" + this.jsonCallbackFunctionName,
	$.ajax({ url: "http://blackfriday.gershoni.com/feed/" + this.brand + ".json?jsoncallback=" + this.jsonCallbackFunctionName,
	         dataType: "script",
			 type: "GET",
			 cache: false,
			 callback: null,
			 success: function (data, textStatus) {
			  // data could be xmlDoc, jsonObj, html, text, etc...
			  //this; // the options for this ajax request
			  //console.log("Got something back for " + self.brand + " " + textStatus + " " + data);
			 },
			 data:null,
			 complete: function (XMLHttpRequest, textStatus) {
			   //this; // the options for this ajax request
			   //console.log("Complete " + XMLHttpRequest + " " + textStatus);
			 }

		  });


/*
	$.getJSON(
	    "http://blackfriday.gershoni.com/bf_feed_jsonp/?brand=" + this.brand + "&count=" + this.max_entries + "&jsoncallback=fixedMethodName",
        function(json){
		   console.log("Got something back for " + this.brand);
		}
	);*/

  }

  this.handleResponse = function(json){
    this.parseJSON(json);
    this.updateInfoDisplay();
    this.resetQueueInterval();
    this.runQueue();
  }

  /**
   * parse the feed
   * @param {Object} json
   */ 
  this.parseJSON = function(json){
    var self = this;

    $.each(json.items, function(i,item){
      var itemDataSource = item.data_source;
      if (!itemDataSource) return null;
		
	  var parsed_item;
      switch (itemDataSource) {
        case "Twitter":
		  parsed_item = BrandFeedParser.twitter(item);
          break;
          
        case "Google News":
		  parsed_item = BrandFeedParser.google_news(item);
          break;
          
        case "Digg":
		  parsed_item = BrandFeedParser.digg(item);
          break;
          
        case "YouTube":
		  parsed_item = BrandFeedParser.youtube(item);
          break;
        
        //case "Images":
        //  parsed_item = BrandFeedParser.images(item);
        //  break;
          
        default:
          // Unknown source?
          return null;
      }
	  
	  // Only add items newer that the oldest currently shown
	  // and skip dups
      if ( (self.all_items.length == 0 || parsed_item.timestamp > self.all_items[self.all_items.length-1].timestamp) &&
	      !self.itemExists(parsed_item) ) {
        self.new_item_queue.addItem(parsed_item);
      }
    });
  }

  // Update the info display
  this.updateInfoDisplay = function(){
    if (this.$queue_length_html) {
      this.$queue_length_html.text("New Items: " + this.new_item_queue.size());
    }
  }
     
  this.resetQueueInterval = function () {
  	// Stop the previous interval
  	clearInterval(this.queueInterval);
	
	// Determine how quickly we need to show items to empty the
	// queue before the next feed pull
	this.queueFrequency = Math.max(1000, Math.floor(this.pullFrequency / this.new_item_queue.size()));
	
	var self = this;
  	this.queueInterval = setInterval( function(){ self.runQueue(); }, this.queueFrequency);
  }
	 
  this.runQueue = function(){
  	if (this.paused) return;
    if (this.new_item_queue.size() == 0) return;
    if (this.queueRunning) return;
	
	// Lock
	this.queueRunning = true;
	
	var self = this;
	
    // Grab the top item	
    var item = this.new_item_queue.getItem();
    
    // Generate its html equiv
    var $item_html = BrandFeedHelper.createItemHtml(item);
    
    // Save reference to the html dom object for later removal/manipulation
    item.$html = $item_html;
    
    // Store it
    this.all_items.unshift(item);
	
    // Show it
    item.$html.css("display", "none");
    this.$itemContainer.prepend(item.$html);
    item.$html.slideDown("slow", function(){
	  // Update the info display when done
      self.updateInfoDisplay();
	  self.updateCallback(self.$domContainer);
    });
    
    // Remove any overflow items
    if (this.all_items.length > this.max_entries) {
      var excess_item = this.all_items.pop();
      excess_item.$html.slideUp("fast", function(){
        $(this).remove();
      });
    }
	
	// Unlock
	this.queueRunning = false;
  }
  
  /**
   * Update all timestamps
   */
  this.updateTimestamp = function () {
    $('.item', this.$itemContainer).each(function(){
      BrandFeedHelper.updateTimestamp($(this));
    });
  }
  
  /**
   * Determine if the item is already in the list, via GUID compare
   * @param {Object} item
   */
  this.itemExists = function(item){
    for (var i = this.all_items.length - 1; i >= 0; i--) {
      if (this.all_items[i].guid == item.guid) {
        return true;
      }
    }
    return false;
  }
}


/**
 * Class: BrandFeedQueue
 */
var BrandFeedQueue = function(){

  this.queue = new Array();
  
  this.addItem = function(item, currentItems){
  	
	// Don't add duplicates to the queue
	if (this.itemExists(item)) return;
	
    this.queue.push(item);
	
	// sort array (oldest first)
    this.queue.sort(this.sortDateAsc);
  }

  this.getItem = function() {
  	var item = this.queue.shift();
  	return item;
  }
  
  this.size = function() {
  	return this.queue.length;
  }
  
  /**
   * Determine if the item is already in the queue, via GUID compare
   * @param {Object} item
   */
  this.itemExists = function(item){
    for (var i = this.queue.length - 1; i >= 0; i--) {
      if (this.queue[i].guid == item.guid) {
        return true;
      }
    }
    return false;
  }
  
  this.sortDateAsc = function(a,b) {return isNaN(a.timestamp - b.timestamp) ? -1 : a.timestamp - b.timestamp;}
  this.sortDateDesc = function(a,b) {return isNaN(b.timestamp - a.timestamp) ? -1 : b.timestamp - a.timestamp;}
}


/**
 * Class: BrandFeedParser
 * Turn feed items into item objects
 */
var BrandFeedParser = new function(){

  this.twitter = function($item){
    var parsed_item = this.commonPreParse($item);
    return parsed_item;
  }
  
  this.google_news = function($item){
    var parsed_item = this.commonPreParse($item);
    
    parsed_item.author_name = "Google News";
    parsed_item.author_url = "http://news.google.com/";
	parsed_item.author_icon = "/wp-content/themes/gershoni/images/black_friday/google_news_icon_32x32.png";
    
    return parsed_item;
  }
  
  this.digg = function($item){
    var parsed_item = this.commonPreParse($item);
    return parsed_item;
  }
  
  this.youtube = function($item){
    var parsed_item = this.commonPreParse($item);
    return parsed_item;
  }
  
  this.images = function($item){
    var parsed_item = this.commonPreParse($item);
    return parsed_item;
  }
  
  this.commonPreParse = function($item){
  
    var timestamp = Date.parse($item.pubDate);
    timestamp = (isNaN(timestamp) ? 0 : timestamp);
    
    var pre_parsed_item = {
      'title': $item.title,
      'text': $item.description,
      'link': $item.link,
      'author_name': $item.author,
      'author_icon': $item.author_image,
      'author_url': $item.author_url,
      'date': $item.pubDate,
      'timestamp': timestamp,
	  'source' : $item.data_source,
	  'guid' : $item.guid
    };
    return pre_parsed_item;
  }
}


// A singleton collection of static helper functions
var BrandFeedHelper = new function () {

  this.createItemHtml = function(item){

    var item_html = $(document.createElement('div')).addClass("item");
    var content_html = $(document.createElement('div')).addClass("content");
	
    if (item.author_icon) {
	  var author_icon_img = $(document.createElement('img'));
	  author_icon_img.attr("src", item.author_icon);
	  author_icon_img.attr("height", 32);
	  author_icon_img.attr("width", 32);
	  
	  var author_icon_link = $(document.createElement('a')).attr("href", item.author_url);
	  author_icon_link.attr("title", item.author_name);
	  author_icon_link.attr("target", "_blank");
	  author_icon_link.append(author_icon_img);
	  
	  var author_icon_html = $(document.createElement('div')).addClass("author_icon");
	  author_icon_html.append(author_icon_link);
	  item_html.append(author_icon_html);
    }
	
	item_html.append(content_html);
	
    var link_html = $(document.createElement('a')).attr("href", item.link);
	link_html.attr("target", "_blank");
    link_html.append(item.title);
    content_html.append(link_html);
    
    content_html.append("<br />");
    
    var author_html = $(document.createElement('a')).attr("href", item.author_url);
	author_html.attr("target", "_blank");
    author_html.append(item.author_name);
    
    var source_html = $(document.createElement('span')).addClass("source");
    source_html.append(author_html);
    source_html.append(" via " + item.source);
	content_html.append(source_html);
	
	var date_html = $(document.createElement('span')).addClass("date");
	date_html.attr("rel", item.timestamp);
	content_html.append(date_html);
    
	// Update the timestamp
	this.updateTimestamp(item_html);
	
    return item_html;
  }
	
	
  /**
   * Grab the given jquery selector item, grab the date stored
   * in the "rel" attribute and update the text to the natural
   * language version
   * @param {Object} $item
   */
  this.updateTimestamp = function($item_html){
    var $date = $(".date", $item_html);
    var timestamp = $date.attr('rel');
    $date.text(" about " + this.timeAgo(timestamp));
  }
  
  
  /**
   * Create a natural language version of the given timestamp
   * @param {Object} timestamp
   */
  this.timeAgo = function(timestamp){
    var now = new Date().getTime();
    var time_difference = now - timestamp;
    time_difference = time_difference / 1000; // convert to seconds
    if (time_difference > 86400) {
      // days
      time_prefix = Math.round(time_difference / 86400);
      if (time_prefix == 1) {
        return 'yesterday';
      }
      if (time_prefix > 31) {
        // months
        time_prefix = Math.round(time_prefix / 31);
        return time_prefix + ' months ago';
      }
      // days
      return time_prefix + ' days ago';
    }
    else 
      if (time_difference > 3600) {
        // hours
        time_prefix = Math.round(time_difference / 3600);
        if (time_prefix == 1) {
          return time_prefix + ' hour ago';
        }
        return time_prefix + ' hours ago';
      }
      else 
        if (time_difference > 60) {
          // minutes
          time_prefix = Math.round(time_difference / 60);
          if (time_prefix == 1) {
            return time_prefix + ' minute ago';
          }
          return time_prefix + ' minutes ago';
        }
        else {
          // seconds
          time_prefix = Math.round(time_difference);
          if (time_prefix <= 0) {
            return 'just now';
          }
          else 
            if (time_prefix == 1) {
              return time_prefix + ' second ago';
            }
          return time_prefix + ' seconds ago';
        }
  }

}