// 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

const NEWS_FEED_ROOT = "urn:flock:feedcontext:news";
Components.utils.import("resource:///modules/FlockStringBundleHelpers.jsm");

var FlockFeeds = {
  URI_FEED_PROPERTIES: "chrome://flock/locale/feeds/feeds.properties",
  FEED_TYPE_PRIORITY: {
    'atom': 5,
    'atom03': 4,
    'rss2': 3,
    'rss1': 2
  },
  discoveredFeeds: {},
  verifiedFeeds: {},
  mediaFeeds: {}
}


FlockFeeds.contextObserver = {
  onSubscribe: function onSubscribe(aContext, aFeed) {},

  onUnsubscribe: function onUnsubscribe(aContext, aFeed) {},

  onUnreadCountChange: function onUnreadCountChange(aContext, aFeed, aSourceId)
  {
    if (aSourceId == NEWS_FEED_ROOT) {
      var newsSBB = document.getElementById("flock_NewsSidebarBroadcaster");
      if (aContext.getRoot().getUnreadCount() > 0) {
        newsSBB.setAttribute("hasNew", true);
      } else {
        newsSBB.removeAttribute("hasNew");
      }
    }
  }
};

// Fills the news button tooltip with the appropriate information
FlockFeeds.newsSetTooltipText = function newsSetTooltip() {
  var unreadCount = FlockFeeds.newsFeedContext.getRoot().getUnreadCount();
  var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
            .getService(Ci.nsIStringBundleService);
  var bundle = sbs.createBundle(FlockFeeds.URI_FEED_PROPERTIES);

  var closeLabel = "flock.feed.tooltip.close";
  var openLabel = "flock.feed.tooltip.open";
  var newsSBB = document.getElementById("flock_NewsSidebarBroadcaster");

  var checked = newsSBB.getAttribute("checked") == "true";
  var tooltip = bundle.GetStringFromName(checked ? closeLabel: openLabel);
  if (unreadCount > 0) {
    var newFeeds = "flock.feed.tooltip.newFeeds";
    tooltip += " " + bundle.formatStringFromName(newFeeds, [unreadCount], 1);
  }
  newsSBB.setAttribute("tooltiptext", tooltip);
};

FlockFeeds.DNDObserver = {
  canDrop: function(aEvent, aDragSession) {
    // Don't allow drops from outside browser or from media bar
    var node = aDragSession.sourceNode;
    if (!node || node.nodeName.toLowerCase() == "photo") {
      return false;
    }
    return true;
  },
    
  onDragOver: function(aEvent, aFlavour, aDragSession) {},
    
  onDragEnter: function(aEvent, aDragSession) {},
    
  onDragExit: function(aEvent, aDragSession) {},

  onDragStart: function(aEvent, aXferData, aDragAction) {},
  
  onDrop: function(aEvent, aXferData, aDragSession) {
    var logger = Cc["@flock.com/logger;1"].createInstance(Ci.flockILogger);
    logger.init("FlockFeeds.DNDObserver:onDrop");

    var url;
    switch(aXferData.flavour.contentType) {
      case "application/x-moz-file":
        var ios = Cc["@mozilla.org/network/io-service;1"]
                  .getService(Ci.nsIIOService);
        var fileHandler = ios.getProtocolHandler("file")
                             .QueryInterface(Ci.nsIFileProtocolHandler);
        url = fileHandler.getURLSpecFromFile(aXferData.data);
        break;

      case "text/x-moz-url":
        url = aXferData.data.split("\n")[0];
        break;
    }

    // Convert the specified string into a URI
    var fixup = Cc["@mozilla.org/docshell/urifixup;1"]
                .getService(Ci.nsIURIFixup);
    try {
      var uri = fixup.createFixupURI(url, fixup.FIXUP_FLAG_NONE);
      url = uri.spec;
    }
    catch (e) {
      logger.error("FlockFeeds.DNDObserver nsIURIFixup exception: " + e.message);
    }

    var feedManager = Cc["@flock.com/feed-manager;1"]
                      .getService(Ci.flockIFeedManager);
    var metrics = Cc["@flock.com/metrics-service;1"]
                  .getService(Ci.flockIMetricsService);
    var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
              .getService(Ci.nsIStringBundleService);
    var bundle = sbs.createBundle(FlockFeeds.URI_FEED_PROPERTIES);
    var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"]
                  .getService(Ci.nsIPromptService);

    // Ensure the url is valid
    if (feedUtils.isValidURL(url)) {
      var feedManagerListener = {
        onGetFeedComplete: function FML_onGetFeedComplete(aFeed) {
          // Add feed to the root
          var newsRoot = FlockFeeds.newsFeedContext.getRoot();
          newsRoot.subscribeURL(url, null);
          metrics.report("FeedsSidebar-AddFeed", "FeedsSidebarDrop");
        },
        onError: function FML_onFeedError(aError) {
          prompts.alert(window,
                        bundle.GetStringFromName("flock.feed.add.error.title"),
                        bundle.formatStringFromName("flock.feed.add.error.msg",
                                                    [url],
                                                    1));
        }
      }
      feedManager.getFeed(uri, feedManagerListener);
    } else {
      // Invalid feed url
      prompts.alert(window,
                    bundle.GetStringFromName("flock.feed.add.error.title"),
                    bundle.formatStringFromName("flock.feed.add.error.msg",
                                                [url],
                                                1));
    }
  },

  getSupportedFlavours: function() {
    var flavourSet = new FlavourSet();
    flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
    flavourSet.appendFlavour("text/x-moz-url");
    return flavourSet;
  }
};

FlockFeeds.progressListener = {
  lastUrl: null,
  currentUrl: null,
  
  onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {},
  
  onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
  
  onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {},

  onSecurityChange: function(aWebProgress, aRequest, aStatus) {},
  
  onLocationChange: function(aWebProgress, aRequest, aLocation) {
    if (aWebProgress.DOMWindow == gBrowser.selectedBrowser.contentWindow) {
      var url = null;
      if (aLocation) {
        // strip anchors
        url = aLocation.spec.replace(/#.*/, "");
      }
      if (this.lastUrl != url) {
        this._newLocation(url);
        this.lastUrl = url;
      }
      FlockFeeds.loadMediaRSS();
    }
  },
  
  _newLocation: function(aUrl) {
    this.currentUrl = aUrl;
    FlockFeeds.updateButton();
  }
};


// handler for LINK elements used in feed discovery
FlockFeeds.linkHandler = {
  logger: Cc["@flock.com/logger;1"].createInstance(Ci.flockILogger),
  feedManager: Cc["@flock.com/feed-manager;1"].getService(Ci.flockIFeedManager),
  ios: Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService),
  
  handleEvent: function (aEvt) {
    var logger = this.logger;
    logger.init("feeddiscovery");

    var element = aEvt.target;
    var documentUrl = element.ownerDocument.URL;

    if (element.localName == "LINK" && element.rel == "alternate") {
      if (element.type == "application/rss+xml" ||
          element.type == "application/atom+xml" ||
          element.type == "text/xml") {
        logger.info("discovered feed: url: " + element.href);
        
        var feedManagerListener = {
          url: documentUrl,
          feedManager: this.feedManager,

          onGetFeedComplete: function(feed)
          {
            var url = feed.getURL();
            var title = feed.getRealTitle();
            var format = feed.getFormat();
            var type = feed.getType();
            var finalURL = feed.getFinalURL();

            logger.info("verified feed: url: " + url.spec + " title: " +
                        title + " type: " + type);

            var documentVerifiedFeeds = FlockFeeds.verifiedFeeds[this.url];
            var documentMediaFeeds = FlockFeeds.mediaFeeds[this.url];

            if (type == Components.interfaces.nsIFeed.TYPE_IMAGE ||
                type == Components.interfaces.nsIFeed.TYPE_VIDEO) {
              documentMediaFeeds.push(feed);
              FlockFeeds.loadMediaRSS();
            }

            for (var c = 0; c < documentVerifiedFeeds.length; c++) {
              var testFeed = documentVerifiedFeeds[c];
              var testFormat = testFeed.getFormat();
              var testType = testFeed.getType();
              var testTitle = testFeed.getRealTitle();
              var testFinalURL = testFeed.getFinalURL();

              if (testFinalURL && finalURL && testFinalURL.equals(finalURL))
                return;

              if (testTitle == title && testFormat != format) {
                if (FlockFeeds.FEED_TYPE_PRIORITY[format] > FlockFeeds.FEED_TYPE_PRIORITY[testFormat]) {
                  documentVerifiedFeeds[c] = feed;
                }
                return;
              }
            }

            documentVerifiedFeeds.push(feed);
            FlockFeeds.updateButton();
          },
          
          onError: function(error)
          {
            /* just ignore, bad feed */
          }
        };

        if (!(documentUrl in FlockFeeds.discoveredFeeds)) {
          FlockFeeds.discoveredFeeds[documentUrl] = [];
          FlockFeeds.verifiedFeeds[documentUrl] = [];
          FlockFeeds.mediaFeeds[documentUrl] = [];
        }

        if (!(element.href in FlockFeeds.discoveredFeeds[documentUrl])) {
          FlockFeeds.discoveredFeeds[documentUrl][element.href] = {title: element.title, type: element.type};
          //try {
            var url = this.ios.newURI(element.href, null, null);
            this.feedManager.getFeedMetadata(url, feedManagerListener);
          //} catch (e) {}
        }
      }
    }
  }
};

FlockFeeds.updateButton = function FF_updateButton() {
  var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
  var stringBundle = stringBundleService.createBundle("chrome://flock/locale/favorites/favorites.properties");
  var url = FlockFeeds.progressListener.currentUrl;
  var feedManager = Cc["@flock.com/feed-manager;1"].getService(Ci.flockIFeedManager);
  var feedBtn = document.getElementById("favoritesFeedButton");
  if ((url in FlockFeeds.verifiedFeeds) &&
      (FlockFeeds.verifiedFeeds[url].length > 0))
  {
    if (feedBtn) {
      feedBtn.removeAttribute("disabled");
    }
    if (FlockFeeds.verifiedFeeds[url].length == 1) {
      var tooltip = stringBundle.GetStringFromName("flock.favs.feeds.desc.1");
    } else {
      var tooltip = stringBundle.formatStringFromName("flock.favs.feeds.desc.2", [FlockFeeds.verifiedFeeds[url].length], 1);
    }
    if (feedBtn) {
      feedBtn.setAttribute("tooltiptext", tooltip);
    }
    for(var i= 0; i< FlockFeeds.verifiedFeeds[url].length; i++)
    {
      var feedURL = FlockFeeds.verifiedFeeds[url][i].getURL();
      if (feedURL && !FlockFeeds.newsFeedContext.existsSubscription(feedURL)) {
        FlockFeeds._showMessage();
        break;
      }
    }
  } else {
    if (feedBtn) {
      feedBtn.setAttribute("disabled", true);
      var tooltip = stringBundle.GetStringFromName("flock.favs.feeds.desc.3");
      feedBtn.setAttribute("tooltiptext", tooltip);
    }
  }
}

FlockFeeds.loadMediaRSS = function FF_loadMediaRSS() {
  var url = FlockFeeds.progressListener.currentUrl;
  if (url in FlockFeeds.mediaFeeds) {
    for (var i = 0; i < FlockFeeds.mediaFeeds[url].length; i++) {
      var feed = FlockFeeds.mediaFeeds[url][i];
      var type = feed.getType();
      if (type == Components.interfaces.nsIFeed.TYPE_IMAGE ||
          type == Components.interfaces.nsIFeed.TYPE_VIDEO)
      {
        MediaNotifications.addMediaRSS(feed);
      }
    }
  }
  MediaNotifications.updateState();
}

FlockFeeds._showMessage = function FF__showMessage() {
  var brand = brandGetString("brand", "brandShortName");
  var message = flockGetString("favorites/favorites",
                               "flock.favs.overlay.discovery-feeds",
                               [brand]);

  var nBox = gBrowser.getNotificationBox();

  var host = gBrowser.currentURI.host;
  // ignore subdomains 
  var domain = host.substring(host.indexOf(".") + 1, host.length);

  if (domain.indexOf(".") == -1) { // host does not have a sub-domain
    domain = host;
  }

  var links = [{
    label: flockGetString("favorites/favorites",
                          "flock.favs.overlay.show-me-how"),
    callback: function() {  
      var bt = document.getElementById("favoritesFeedButton");
      if (bt) {
        bt.firstChild.showPopup(bt, -1, -1, "popup", "bottomleft", "topleft");
        var method = function sM_cb_method() {
          var elt = document.getElementById("favoritesFeedButton");
          notificationOverlay.flash(0, elt);
        }
        setTimeout(method, 500);
      }
    }
  }];

  nBox.appendUniqueNotification(message,
                                "feeds-discovered",
                                "chrome://flock/skin/feeds/feed.png",
                                nBox.FLOCK_PRIORITY_LOW,
                                null,
                                links,
                                domain);
}

FlockFeeds.onClick = function FF_onClick() {
  var documentFeeds = this.verifiedFeeds[this.progressListener.currentUrl];
  if (documentFeeds.length == 1) {
    FlockFeeds.openFeed(documentFeeds[0].getURL().spec);
  } else {
    var btn = document.getElementById("favoritesFeedButton");
    btn.firstChild.showPopup(btn, -1, -1, "popup", "bottomleft", "topleft");
  }
}

FlockFeeds.openFeed = function FF_openFeed(urlSpec) {
  var metrics = Cc["@flock.com/metrics-service;1"]
                .getService(Ci.flockIMetricsService);
  metrics.report("FeedsSidebar-Open", "Discovery");
  openUILinkIn(urlSpec, "current");
}

FlockFeeds.updatePopup = function FF_updatePopup() {
  var documentVerifiedFeeds = FlockFeeds.verifiedFeeds[FlockFeeds.progressListener.currentUrl]; 

  var feedButton = document.getElementById("favoritesFeedButton");
  // Is the feedbutton on the chrome?
  if (!feedButton) {
    return;
  }
  var container = feedButton.firstChild;

  while (container.lastChild)
    container.removeChild(container.lastChild);
  
  var feedManager = Cc["@flock.com/feed-manager;1"].getService(Ci.flockIFeedManager);
  
  var feed, newMenuItem, url, title, attrs;
  for (var c = 0; c < documentVerifiedFeeds.length; c++) {
    feed = documentVerifiedFeeds[c];
    newMenuItem = document.createElement("menuitem");

    url = feed.getURL();

    attrs = { class: "flock-discovered-feeds-item menuitem-iconic",
                  oncommand: "FlockFeeds.openFeed('" + url.spec + "'); "
                             + "event.stopPropagation();"
                };

    if (url && FlockFeeds.newsFeedContext.existsSubscription(url)) {
      attrs.image = "chrome://flock/skin/common/star16.png";
      attrs.label = feed.getTitle();
    } else {
      attrs.label = feed.getRealTitle();
    }

    for (p in attrs) {
      newMenuItem.setAttribute(p, attrs[p]);
    }

    var parity = (c % 2 == 0) ? "even" : "odd";
    newMenuItem.setAttribute("parity", parity);
    container.appendChild(newMenuItem);
  }
}

FlockFeeds.openSidebar = function FF_openSidebar(aMetricsValue) {
  if (!document.getElementById("flock_NewsSidebarBroadcaster").getAttribute("checked")) {
    toggleSidebarWithMetric("flock_NewsSidebarBroadcaster",
                            "FeedsSidebar-Open",
                            null,
                            aMetricsValue);
  }
}

FlockFeeds.init = function FF_init() {
  if (!FlockFeeds.newsFeedContext) {
    var feedManager = Cc["@flock.com/feed-manager;1"]
                      .getService(Ci.flockIFeedManager);
    FlockFeeds.newsFeedContext = feedManager.getFeedContext("news");
    FlockFeeds.newsFeedContext.addObserver(FlockFeeds.contextObserver);

    // init the icon state
    var co = FlockFeeds.contextObserver;
    co.onUnreadCountChange(FlockFeeds.newsFeedContext, null, NEWS_FEED_ROOT);

    // add feed discovery listener
    gBrowser.addEventListener("DOMLinkAdded", FlockFeeds.linkHandler, false);
    gBrowser.addProgressListener(FlockFeeds.progressListener,
                                 Ci.nsIWebProgress.NOTIFY_LOCATION);
  }
}

FlockFeeds.uninit = function FF_uninit() {
  if (FlockFeeds.newsFeedContext) {
    FlockFeeds.newsFeedContext.removeObserver(FlockFeeds.contextObserver);
    gBrowser.removeProgressListener(FlockFeeds.progressListener);
    FlockFeeds.newsFeedContext = null;
  }
}

window.addEventListener("load", FlockFeeds.init, false);
window.addEventListener("unload", FlockFeeds.uninit, false);
