String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }

function Callback(container, spider, tab) 
{ 
  this.container = container;
  this.spider = spider; 
  this.tab = tab; 
  var me = this;
  this.invoke = function(event)
  {
    videofinder.DiggVideoComplete(me.container, me, me.spider, me.tab);
  }
};

var logger = 
{
  consoleService: null,

  init: function()
  {
    consoleService = Components.classes["@mozilla.org/consoleservice;1"] .getService(Components.interfaces.nsIConsoleService); 
  },

  Log: function(msg)
  {
    consoleService.logStringMessage(msg); 
  }
};

var videofinder =  
{
  movieExtensions: "|.asf|.wma|.wmv|.wm|.wax|.wvx|.wpl|.dvr-ms|.wmd|.avi|.mpg|.mpeg|.m1v|.mpe|.mpv2|.divx|.mov|.mp4|.ivf|.qt|.m4v|",
  tabs: null,
  prefs: null,
  activeTab: null,
  youtubeCgi: "",

  onLoad: function() 
  {
    this.strings = document.getElementById("videofinder-strings");

    var browser = document.getElementById("content");
    browser.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
    this.tabs = new Array();

    logger.init();

    this.prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch2);
  },

  onMenuItemCommand: function(e) 
  {
    if (this.activeTab == null || (this.activeTab.videoUrls.length == 0 && this.activeTab.videocastUrls.length == 0))
    {
      return;
    }

    var s = "";
    // get temporary directory
    var file = Components.classes["@mozilla.org/file/directory_service;1"]
                         .getService(Components.interfaces.nsIProperties)
                         .get("TmpD", Components.interfaces.nsIFile);

    if (file)
    {
      file.append("videos.tmp");
      file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0777);
      var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);

      foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate foStream.write(data, data.length); foStream.close();
      s = "<VideoFinder>\n";
      if (this.activeTab.videoUrls.length > 0)
      {
        s += "  <Videos>\n";
        for (var i = 0; i < this.activeTab.videoUrls.length; ++i)
        {
          s += "    <Video>\n";
          s += "      <URL>" + this.activeTab.url + "</URL>\n";
          s += "      <Filename>" + this.activeTab.videoUrls[i].filename + "</Filename>\n";
          s += "      <Title>" + this.activeTab.videoUrls[i].title + "</Title>\n";
          s += "      <Description>" + this.activeTab.videoUrls[i].description + "</Description>\n";
          s += "      <Broadcaster>" + this.activeTab.videoUrls[i].publisher + "</Broadcaster>\n";
          s += "      <FlvLength>" + this.activeTab.videoUrls[i].length + "</FlvLength>\n";
          s += "      <VideoURL>" + this.activeTab.videoUrls[i].url + "</VideoURL>\n";
          s += "    </Video>\n";
        }
        s += "  </Videos>\n";
      }
      if (this.activeTab.videocastUrls.length > 0)
      {
        s += "  <VideoCasts>\n";
        for (var i = 0; i < this.activeTab.videocastUrls.length; ++i)
        {
          s += "    <VideoCast>\n";
          s += "      <URL>" + this.activeTab.url + "</URL>\n";
          s += "      <Title>" + this.activeTab.videocastUrls[i].title  + "</Title>\n";
          s += "      <VideoCastURL>" + this.activeTab.videocastUrls[i].url + "</VideoCastURL>\n";
          s += "    </VideoCast>\n";
        }
        s += "  </VideoCasts>\n";
      }
      s += "</VideoFinder>\n";

      foStream.write(s, s.length);
      foStream.close();
    }

    location.href = "veoh://www.veoh.com?Command=17A9D674-7454-412f-A401-548EC552D5B6&FilePath=" + file.path;
    //alert("veoh://www.veoh.com?Command=17A9D674-7454-412f-A401-548EC552D5B6&FilePath=" + file.path);
  },

  onToolbarButtonCommand: function(e) 
  {
    videofinder.onMenuItemCommand(e);
  },

  CleanFilename: function(filename)
  {
    var result = "";
    for (var i = 0; i < filename.length; ++i)
    {
      if ((filename[i] >= 'a' && filename[i] <= 'z') ||
          (filename[i] >= 'A' && filename[i] <= 'Z') ||
          (filename[i] >= '0' && filename[i] <= '9'))
      {
        result += filename[i];
      }
    }

    return result;
  },

  CleanTitle: function(title)
  {
    var result = "";

    for (var i = 0; i < title.length; ++i)
    {
      var v = title.charCodeAt(i);

      if (v >= 32 && v < 128)
      {
        result += String.fromCharCode(v);
      }
    }

    return result;
  },

  FindTab: function(url)
  {
    for (var i = 0; i < this.tabs.length; ++i)
    {
      if (this.tabs[i].url == url)
      {
        return this.tabs[i];
      }
    }

    return null;
  },

  XmlEncode: function(str)
  {
    return str.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;').replace('\'','&apos;').replace('"','&quot;');
  },

  DeleteTab: function(url)
  {
    for (var i = 0; i < this.tabs.length; ++i)
    {
      if (this.tabs[i].url  == url)
      {
        this.tabs.splice(i, 1);
        return;
      }
    }
  },

  SetDOMWindow: function(DOMWindow, url)
  {
    var tab = this.FindTab(url);

    if (!tab)
    {
      tab = new Object();

      tab.DOMWindow = DOMWindow;
      tab.document = DOMWindow.document;
      tab.url = url;
      tab.title = "";
      tab.parts = this.SplitUrl(url);
      tab.parsed = false;
	tab.rssUrls = null;
      tab.activeRssUrl = null;
      tab.activeMySpaceUrl = null;
      tab.activeLiveVideoUrl = null;
      tab.activeDiggUrl = null;

      tab.videoUrls = new Array();
      tab.videocastUrls = new Array();
      tab.rssUrls = new Array();
      tab.livevideoUrls = new Array();
      tab.myspaceUrls = new Array();
      tab.metacafeUrls = new Array();
      tab.diggUrls = new Array();

      tab.onUnload = function(e) { videofinder.DeleteTab(url); }

      DOMWindow.addEventListener("unload", tab.onUnload, true);

      this.tabs.push(tab);

      if (typeof(url) == "string" && url.indexOf("http") == 0)
      {
        this.StartProgress();
      }
    }
    else
    {
      if (tab.parsed || typeof(url) != "string" || url.indexOf("http") < 0)
      {
        this.StopProgress();
      }
      else
      {
        this.StartProgress();
      }
    }

    this.activeTab = tab;

    this.UpdateStats(tab);
  },

  SplitUrl: function(url)
  {
    var parts = new Object();

    parts.scheme = "";
    parts.domain = "";
    parts.path = "";
    parts.file = "";
    parts.name = "";
    parts.extension = "";
    parts.anchor = "";
    parts.cgi = "";

    var cgi = url.indexOf("?");

    if (cgi >= 0)
    {
      parts.cgi = url.substring(cgi + 1, url.length);
      url = url.substring(0, cgi);
    }

    var anchor = url.indexOf("#");

    if (anchor >= 0)
    {
      parts.anchor = url.substring(anchor + 1, url.length);
      url = url.substring(0, anchor);
    }

    var scheme = url.indexOf("://");

    if (scheme >= 0)
    {
      parts.scheme = url.substring(0, scheme);
      url = url.substring(scheme + 3, url.length);

      var domain = url.indexOf("/");

      if (domain >= 0)
      {
        parts.domain = url.substring(0, domain);
        url = url.substring(domain, url.length);
      }
    }

    var path = url.lastIndexOf("/");

    if (path >= 0)
    {
      parts.path = url.substring(0, path + 1);
      url = url.substring(path + 1, url.length);
    }

    var extension = url.lastIndexOf(".");

    if (extension >= 0)
    {
      parts.file = url;
      parts.name = url.substring(0, extension);
      parts.extension = url.substring(extension, url.length);
    }
    else
    {
      parts.path += url;
    }

    // alert("URL:" + orig  + "\nSCHEME:" + parts.scheme + "\nDOMAIN:" + parts.domain + "\nPATH" + parts.path + "\nFILE:" + parts.file + "\nEXTENSION:" + parts.extension + "\nANCHOR:" + parts.anchor + "\nCGI:" + parts.cgi);

    return parts;
  },

  ExtractText: function(node)
  {
    if (node.firstChild == null)
    {
      if (node.nodeValue != null)
      {
        return node.nodeValue; 
      }
      if (node.nodeName.toUpperCase() == "BR")
      {
        return "\n";
      }
      return "";
    }
    else
    {
      var result = "";
      var childNode = node.firstChild;
      while (childNode != null)
      {
        result += this.ExtractText(childNode);
        try
        {
          childNode = childNode.nextSibling;
        }
        catch (err)
        {
          childNode = null;
        }
      }
      return result;
    }
  },

  GetSubNodes: function(node)
  {
    var subnodes = new Array();

    for (var i = 0; i < node.childNodes.length; ++i)
    {
      subnodes.push(node.childNodes[i]);
    }

    var subsubnodes = new Array();

    for (var i = 0; i < subnodes.length; ++i)
    {
      subsubnodes = Array.concat(subsubnodes, this.GetSubNodes(subnodes[i]));
    }

    return Array.concat(subnodes, subsubnodes);
  },

  AddVideo: function(list, video)
  {
    for (var i = 0; i < list.length; ++i)
    {
      if (list[i].url == video.url)
      {
        return;
      }
    }
    list.push(video);
  },

  AddRssFeed: function(list, videocast)
  {
    for (var i = 0; i < list.length; ++i)
    {
      if (list[i].url == videocast.url)
      {
        return;
      }
    }
    list.push(videocast);
  },

  ProcessNextMetacafeVideo: function(tab)
  {
    if (tab.metacafeUrls.length > 0)
    {
      var url = tab.metacafeUrls.pop();

      tab.xmlhttp = new XMLHttpRequest(); 

      tab.xmlhttp.onreadystatechange = function() { if (tab.xmlhttp.readyState == 4) videofinder.MetacafeComplete(tab); }
      tab.xmlhttp.open("GET", url, true);
      tab.xmlhttp.send(null);
    }
    else
    {
      this.StopProgress();
    }
  },

  MetacafeComplete: function(tab)
  {
    if (tab.xmlhttp.status == 200)
    {
      // DOM comes back null - assume because content type was text/html - force back into dom
      var parser = new DOMParser();
      var xml = parser.parseFromString(tab.xmlhttp.responseText, "text/xml");

      var items = xml.getElementsByTagName("item");

      for (var i = 0; i < items.length; ++i)
      {
        var video = new Object();

        video.title = this.CleanTitle(items[i].getAttribute("title"));
        video.description = items[i].getAttribute("description");
        video.publisher = "";
        video.length = "";
        video.url = items[i].getAttribute("url");
        video.filename = this.CleanFilename(video.title) + ".flv";

        if (video.url.length > 0)
        {
          this.AddVideo(tab.videoUrls, video);

          if (tab == this.activeTab)
          {
            this.UpdateStats(tab);
          }
        }
      }      
    }

    this.ProcessNextMetacafeVideo(tab);
  },

  ProcessNextMySpaceVideo: function(tab)
  {
    if (tab.myspaceUrls.length > 0)
    {
      tab.activeMySpaceUrl = tab.myspaceUrls.pop();
      url = "http://mediaservices.myspace.com/services/rss.ashx?type=video&mediaID=" + tab.activeMySpaceUrl.id;

      tab.xmlhttp = new XMLHttpRequest(); 

      tab.xmlhttp.onreadystatechange = function() { if (tab.xmlhttp.readyState == 4) videofinder.MySpaceComplete(tab); }
      tab.xmlhttp.open("GET", url, true);
      tab.xmlhttp.send(null);
    }

    this.ProcessNextMetacafeVideo(tab);
  },

  MySpaceComplete: function(tab)
  {
    if (tab.xmlhttp.status == 200)
    {
      var xml = tab.xmlhttp.responseXML;

      var items = xml.getElementsByTagName("item");

      for (var i = 0; i < items.length; ++i)
      {
        var titles = items[i].getElementsByTagName("title");
        if (titles.length == 1)
        {
          var title = titles[0];
          var firstChild = title.firstChild;

          tab.title = this.CleanTitle(firstChild.nodeValue);
        }

        var contents = items[i].getElementsByTagName("content");

        if (contents.length == 1)
        {
          var attributes = contents[0].attributes;

          for (var j = 0; j < attributes.length; ++j)
          {
            if (attributes[j].name == "url")
            {
              var video = new Object();

              video.title = tab.title;
              video.description = tab.activeMySpaceUrl.description;
              video.publisher = tab.activeMySpaceUrl.publisher;
              video.length = "";
              video.url = attributes[j].value;
              video.filename = this.CleanFilename(video.title) + ".flv";

              this.AddVideo(tab.videoUrls, video);

              if (tab == this.activeTab)
              {
                this.UpdateStats(tab);
              }
            }
          }
        }
      }
    }

    this.ProcessNextMySpaceVideo(tab);
  },

  ProcessNextLiveVideo: function(tab)
  {
    if (tab.livevideoUrls.length > 0)
    {
      tab.activeLiveVideoUrl = tab.livevideoUrls.pop();
      var url = tab.activeLiveVideoUrl.url;

      tab.xmlhttp = new XMLHttpRequest();

      tab.xmlhttp.onreadystatechange = function() { if (tab.xmlhttp.readyState == 4) videofinder.LiveVideoComplete(tab); }
      tab.xmlhttp.open("GET", url, true);
      tab.xmlhttp.send(null);
    }
    else
    {
      this.ProcessNextMySpaceVideo(tab);
    }
  },

  LiveVideoComplete: function(tab)
  {
    if (tab.xmlhttp.status == 200)
    {
      pairs = tab.xmlhttp.responseText.split("&");

      for (var i = 0; i < pairs.length; ++i)
      {
        lr = pairs[i].split("=");

        if (lr.length == 2 && lr[0] == "video_id")
        {
          var video = new Object();

          video.title = this.CleanTitle(tab.title);
          video.description = tab.activeLiveVideoUrl.description;
          video.publisher = "";
          video.length = "";
          video.url = unescape(lr[1]);
          video.filename = this.CleanFilename(video.title) + ".flv";

          this.AddVideo(tab.videoUrls, video);

          if (tab == this.activeTab)
          {
            this.UpdateStats(tab);
          }
        }
      }
    }

    this.ProcessNextLiveVideo(tab);
  },

  ProcessNextDiggVideo: function(tab)
  {
    if (tab.diggUrls.length > 0)
    {
      url = tab.diggUrls.pop();
      tab.activeDiggUrl = url;

      var container = document.getElementById("veoh-spider-panel");
      var spider = document.createElement("iframe");

      spider.setAttribute("width", "0");
      spider.setAttribute("height", "0");
      spider.setAttribute("style", "visibility: hidden");

      container.appendChild(spider);

      var c = new Callback(container, spider, tab);

      spider.contentWindow.addEventListener("load", c.invoke, true);

      spider.setAttribute("src", url);
    }
    else
    {
      this.ProcessNextLiveVideo(tab);
    }
  },

  DiggVideoComplete: function(container, callback, spider, tab)
  {
    var tempTab = new Object();

    tempTab.DOMWindow = null;
    tempTab.document = spider.contentDocument;
    tempTab.title = this.CleanTitle(tempTab.document.title);
    tempTab.url = tab.activeDiggUrl;
    tempTab.parts = this.SplitUrl(tempTab.url);
    tempTab.parsed = false;
    tempTab.rssUrls = null;
    tempTab.activeRssUrl = null;
    tempTab.activeMySpaceUrl = null;
    tempTab.activeLiveVideoUrl = null;

    tempTab.videoUrls = new Array();
    tempTab.videocastUrls = new Array();
    tempTab.rssUrls = new Array();
    tempTab.livevideoUrls = new Array();
    tempTab.myspaceUrls = new Array();
    tempTab.metacafeUrls = new Array();

    this.HandleUrl(tempTab);

    tab.videoUrls = tab.videoUrls.concat(tempTab.videoUrls);
    tab.videocastUrls = tab.videocastUrls.concat(tempTab.videocastUrls);
    tab.rssUrls = tab.rssUrls.concat(tempTab.rssUrls);
    tab.livevideoUrls = tab.livevideoUrls.concat(tempTab.livevideoUrls);
    tab.myspaceUrls = tab.myspaceUrls.concat(tempTab.myspaceUrls);
    tab.metacafeUrls = tab.metacafeUrls.concat(tempTab.metacafeUrls);

    spider.contentWindow.removeEventListener("load", callback.invoke, true);

    spider.setAttribute("src", "about:blank");

    spider.contentWindow.close();

    container.removeChild(spider);

    if (tab == this.activeTab)
    {
      this.UpdateStats(tab);
    }

    this.ProcessNextDiggVideo(tab);    
  },


  ProcessNextRssFeed: function(tab)
  {
    if (tab.rssUrls.length > 0)
    {
      url = tab.rssUrls.pop();


      tab.activeRssUrl = url;

      tab.xmlhttp = new XMLHttpRequest(); 

      tab.xmlhttp.onreadystatechange = function() { if (tab.xmlhttp.readyState == 4) videofinder.RssFeedComplete(tab); }
      tab.xmlhttp.open("GET", url, true);
      tab.xmlhttp.send(null);
    }
    else
    {
      this.ProcessNextDiggVideo(tab);
    }
  },

  RssFeedComplete: function(tab)
  {
    if (tab.xmlhttp.status == 200)
    {
      if (tab.xmlhttp.responseXML)
      {
        var rss = tab.xmlhttp.responseXML.getElementsByTagName("rss");

        if (rss.length > 0)
        {
          var title = this.CleanTitle(tab.title);

          var titles = tab.xmlhttp.responseXML.getElementsByTagName("title");

          if (titles.length > 0)
          {
            title = titles[0].firstChild.nodeValue;
          }

          var enclosures = tab.xmlhttp.responseXML.getElementsByTagName("enclosure");

          for (var j = 0; j < enclosures.length; ++j)
          {
            var url = enclosures[j].getAttribute("url");

            if (this.IsMovieUrl(url))
            {

              var videocast = new Object();
              videocast.title = this.CleanTitle(title);
              videocast.url = tab.activeRssUrl;

              this.AddRssFeed(tab.videocastUrls, videocast);

              if (tab == this.activeTab)
              {
                this.UpdateStats(tab);
              }
              break;
            }
          }
        }
      }
      else
      {
        //alert("TEXT:" + tab.xmlhttp.responseText);
      }
    }

    this.ProcessNextRssFeed(tab);    
  },

  MatchesDomain: function(host, domain)
  {
    return host == domain || host.indexOf("." + domain) > 0;
  },

  previousUrl: "",

  ParseVideos: function(url)
  {
    var reparse = false;

    if (url == "about:document-onload-blocker")
    {
      url = previousUrl;

      reparse = true;
    }
    else
    {
      previousUrl = url;
    }

    var tab = this.FindTab(url);

    if (!tab || (tab.parsed && !reparse))
    {
      this.StopProgress();

      if (tab)
      {
        this.UpdateStats(tab);
      }

      return;
    }

    tab.title = this.CleanTitle(tab.document.title);

    tab.parsed = true;

    this.HandleUrl(tab);

    this.ProcessNextRssFeed(tab);

    if (this.activeTab == tab)
    {
      this.UpdateStats(tab);
    }
  },

  HandleUrl:function(tab)
  {
    this.ParseVideoFiles(tab);

    this.ParseRssFeed(tab);

    if (this.MatchesDomain(tab.parts.domain, "veoh.com"))
    {
      this.ParseVeohVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "youtube.com"))
    {
      this.ParseYouTubeVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "metacafe.com"))
    {
      this.ParseMetaCafeVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "livevideo.com"))
    {
      this.ParseLiveVideoVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "myspace.com"))
    {
      this.ParseMySpaceVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "video.google.com"))
    {
      this.ParseGoogleVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "dailymotion.com"))
    {
      this.ParseDailyMotionVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "break.com"))
    {
      this.ParseBreakVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "imeem.com"))
    {
      this.ParseImeemVideos(tab);
    }
    else if (this.MatchesDomain(tab.parts.domain, "digg.com"))
    {
      if (tab.parts.path.indexOf("/videos") == 0)
      {
        this.ParseDiggVideos(tab);
      }
    }
  },

  IsMovieUrl:function (url)
  {
    var parts = this.SplitUrl(url);

    if (this.movieExtensions.indexOf("|" + parts.extension.toLowerCase() + "|") >= 0)
    {
        return true;
    }

    return false;
  },

  ParseVideoFiles: function(tab)
  {
    var links = tab.document.getElementsByTagName("a");

    var videoCount = 0;
    var rssCount = 0;

    for (var i = 0; i < links.length; ++i)
    {
      var parts = this.SplitUrl(links[i].href);

      if (this.IsMovieUrl(links[i].href))
      {
        var video = new Object();

        var left = unescape(parts.name);
        var right = this.ExtractText(links[i]);
        var title = "";

        if (left == "" && right == "")
        {
          title = this.CleanTitle(tab.title);
        }
        else
        {
          title = (left + " " + right).trim();
        }

        video.title = this.CleanTitle(title);
        video.description = "";
        video.publisher = "";
        video.length = "";
        video.url = links[i].href;
        video.filename = this.CleanFilename(video.title) + parts.extension;

        this.AddVideo(tab.videoUrls, video);
      }

      if (parts.extension == ".xml" || parts.extension == ".rss")
      {
        tab.rssUrls.push(links[i].href);
      }
    }

    links = tab.document.getElementsByTagName("link");

    for (var i = 0; i < links.length; ++i) 
    {
      if (links[i].type == "application/rss+xml")
      {
        tab.rssUrls.push(links[i].href);
      }
    }
  },

  ParseRssFeed: function(tab)
  {
    var rss = tab.document.getElementsByTagName("rss");

    if (rss.length > 0)
    {
      var title = this.CleanTitle(tab.title);

      var titles = tab.document.getElementsByTagName("title");

      if (titles.length > 0)
      {
        title = titles[0].firstChild.nodeValue;
      }

      var enclosures = tab.document.getElementsByTagName("enclosure");
      for (var i = 0; i < enclosures.length; ++i)
      {
        var url = enclosures[i].getAttribute("url");
        if (this.IsMovieUrl(url))
        {
          var videocast = new Object();
          videocast.title = this.CleanTitle(title);
          videocast.url = tab.url;
          tab.videocastUrls.push(videocast);
          return;
        }
      }
    }
  },

  ParseVeohVideos: function(tab)
  {
    var links = tab.document.getElementsByTagName("link");

    for (var i = 0; i < links.length; ++i)
    {
      if (links[i].type == "application/veoh+Video")
      {
        var video = new Object();

        var title = links[i].getAttribute("title").replace(/\+/g, ' ');

        video.title = this.CleanTitle(unescape(title));
        video.description = "";
        video.publisher = "";
        video.length = "";
        video.url = links[i].href;
        video.filename = this.CleanFilename(video.title);

        this.AddVideo(tab.videoUrls, video);
      }
      else if (links[i].type == "application/veoh+RSS")
      {
        var videocast = new Object();

        var title = links[i].getAttribute("title").replace(/\+/g, ' ');

        videocast.title = this.CleanTitle(unescape(title));
        videocast.url = links[i].href;

        this.AddRssFeed(tab.videocastUrls, videocast);
      }
    }
  },

  ParseYouTubeVideos: function(tab)
  {
    var scripts = tab.document.getElementsByTagName("script");

    for (var i = 0; i < scripts.length; ++i)
    {
      var str = scripts[i].innerHTML;

      var start = str.indexOf("watch_fullscreen?");

      if (start >= 0)
      {
        start += 17;

        var end = str.indexOf("'", start);
        var end2 = str.indexOf('"', start);

	  if (end2 < end && end2 > 0)
        {
          end = end2;
        }

        var title = tab.title;
        var length = "0";
        var publisher = "";

        if (end > start)
        {
          var data = str.substr(start, end - start);

          var pairs = data.split("&");

          for (var k = 0; k < pairs.length; ++k)
          {
            var lr = pairs[k].split("=");

            if (lr.length == 2 && lr[0] == "title" && lr[1] != "")
            {
              title = lr[1];
            }

            if (lr.length == 2 && lr[0] == "l")
            {
              length = lr[1];
            }
          }

          var desc1 = tab.document.getElementById("videoDescBegin");
          var desc2 = tab.document.getElementById("videoDescRemain");

          if (desc1 == null)
          {
            desc1 = tab.document.getElementById("vidDescBegin");
          }

          if (desc2 == null)
          {
            desc1 = tab.document.getElementById("vidDescRemain");
          }

          var description = "";

          if (desc2 != null)
          {
            description = this.ExtractText(desc2);
          }
          else if (desc1 != null)
          {
            description = this.ExtractText(desc1);
          }
         
          var video = new Object();

          video.title = this.CleanTitle(title);
          video.description = description;
          video.publisher = publisher;
          video.length = length;
          video.url = "http://www.youtube.com/get_video?" + data;
          video.filename = this.CleanFilename(video.title) + ".flv";

          this.AddVideo(tab.videoUrls, video);        
        }
      }
    }
  },

  ParseMetaCafeVideos: function(tab)
  {
    var player = tab.document.getElementById("fpObj");

    if (player)
    {
      var flashvars = player.getAttribute("flashvars");

      if (flashvars)
      {
        var pairs = flashvars.split("&");

        var itemId = "";
        var leid = "";

        for (var i = 0; i < pairs.length; ++i)
        {
          var lr = pairs[i].split("=");

          if (lr.length == 2 && lr[0] == "itemID")
          {
            itemId = lr[1];
          }

          if (lr.length == 2 && lr[0] == "LEID")
          {
            leid = lr[1];
          }
        }

        if (itemId.length > 0 && leid.length > 0)
        {
          tab.metacafeUrls.push("http://www.metacafe.com/fplayer.php?itemID=" + itemId + "&t=site&fs=n&LEID=" + leid + "&prefixAdID=&suffixAdID=");
        }
      }
    }
  },

  ParseLiveVideoVideos: function(tab)
  {
    var player = tab.document.getElementById("FlashPlay");

    if (player)
    {
      var parts = this.SplitUrl(player.src);

      var pairs = parts.cgi.split("&");

      for (var i = 0; i < pairs.length; ++i)
      {
        lr = pairs[i].split("=");

        if (lr.length == 2)
        {
          if (lr[0] == "video")
          {
            var description = "";
            var metas = tab.document.getElementsByTagName("meta");
            for (var j = 0; j < metas.length; ++j)
            {
              if (metas[j].getAttribute("name").toLowerCase() == "description")
              {
                description = metas[j].getAttribute("content");
              }
            }
               
            var liveVideoUrl = new Object();
            liveVideoUrl.url = unescape(lr[1]) + "&f=flash8"
            liveVideoUrl.description = description;
	      tab.livevideoUrls.push(liveVideoUrl);
          }
        }
      }
    }
    else
    {
      var embeds = tab.document.getElementsByTagName("embed");

      for (var i = 0; i < embeds.length; ++i) 
      {
        var src = embeds[i].src;

        if (src.indexOf("flvplayer") >= 0)
        {
          var parts = this.SplitUrl(src);

          var pairs = parts.cgi.split("&");

          for (var j = 0; j < pairs.length; ++j)
          {
            lr = pairs[j].split("=");

            if (lr.length == 2)
            {
              if (lr[0] == "video")
              {
                var description = "";
                var metas = tab.document.getElementsByTagName("meta");
                for (var k = 0; k < metas.length; ++k)
                {
                  if (metas[k].getAttribute("name").toLowerCase() == "description")
                  {
                    description = metas[k].getAttribute("content");
                  }
                }
                var liveVideoUrl = new Object();
                liveVideoUrl.url = unescape(lr[1]) + "&f=flash8"
                liveVideoUrl.description = description;
	          tab.livevideoUrls.push(liveVideoUrl);
              }
            }
          }
        }
      }
    }
  },

  ParseMySpaceVideos: function(tab)
  {
    var player = tab.document.getElementById("vplayer");

    if (player)
    {
      var attributes = player.attributes;

      for (var i = 0; i < attributes.length; ++i)
      {
        if (attributes[i].name == "flashvars")
        {
          var pairs = attributes[i].value.split("&");
          for (var j = 0; j < pairs.length; ++j)
          {
            var lr = pairs[j].split('=');

            if (lr.length == 2 && lr[0] == "m")
            {
              var bs = tab.document.getElementsByTagName("b");

              var description = "";
              for (var j = 0; j < bs.length; ++j)
              {
                if (bs[j].firstChild.nodeValue == "Description:")
                {
                  description = bs[j].nextSibling.nodeValue;
                  break;
                }
              }

              var tds = tab.document.getElementsByTagName("td");
              var publisher = "";
              for (var j = 0; j < tds.length; ++j)
              {
                if (tds[j].getAttribute("class") == "vidsDetailUserText padL10")
                {
                  var nodes = this.GetSubNodes(tds[j]);

                  for (var k = 0; k < nodes.length && publisher.length == 0; ++k)
                  {
                    if (nodes[k].nodeName.toUpperCase() == "A")
                    {
                      publisher = nodes[k].firstChild.nodeValue;
                    }
                  }
                }
              }
              
              var myspaceUrl = new Object();
              myspaceUrl.id = lr[1];
              myspaceUrl.description = description;
              myspaceUrl.publisher = publisher;
              tab.myspaceUrls.push(myspaceUrl);
            }
          }
        }
      }
    }
  },

  ParseGoogleVideos: function(tab)
  {
    var player = tab.document.getElementById("VideoPlayback");

    if (player)
    {
      var parts = this.SplitUrl(player.src);

      var pairs = parts.cgi.split("&");

      for (var i = 0; i < pairs.length; ++i)
      {
        lr = pairs[i].split("=");

        if (lr.length == 2)
        {
          if (lr[0] == "videoUrl")
          {
            var description = "";
            var descriptionNode = tab.document.getElementById("description");
            if (descriptionNode != null)
            {
              description = this.ExtractText(descriptionNode);
            }

            var video = new Object();

            video.title = this.CleanTitle(tab.title);
            video.description = description;
            video.publisher = "";
            video.length = "";
            video.url = unescape(lr[1]);
            video.filename = this.CleanFilename(video.title) + ".flv";

            this.AddVideo(tab.videoUrls, video);
          }
        }
      }
    }
  },

  ParseDailyMotionVideos: function(tab)
  {
    var player = tab.document.getElementById("video_player");

    if (player)
    {
      var attributes = player.attributes;

      for (var i = 0; i < attributes.length; ++i)
      {
        if (attributes[i].name == "flashvars")
        {
          var pairs = attributes[i].value.split("&");

          for (var j = 0; j < pairs.length; ++j)
          {
            var lr = pairs[j].split('=');

            if (lr.length == 2)
            {
              if (lr[0] == "url")
              {
                var title = this.CleanTitle(tab.title);

                var titleNode = tab.document.getElementsByTagName("h1");

                if (titleNode && titleNode.length > 0)
                {
                  title = this.CleanTitle(this.ExtractText(titleNode[0]));
                }

                var description = "";

                var divs = tab.document.getElementsByTagName("div");

                if (divs)
                {
                  for (var k = 0; k < divs.length; ++k)
                  {
                    if (divs[k].className == "description foreground")
                    {
                      description = this.ExtractText(divs[k]);
                      break;
                    }
                  }
                }

                var publisher = "";
                var iNodes = tab.document.getElementsByTagName("i");

                if (iNodes)
                {
                  for (var k = 0; k < iNodes.length; ++k)
                  {
                    var aNodes = iNodes[k].getElementsByTagName("a");

                    if (aNodes && aNodes.length > 0)
                    {
                      publisher = this.ExtractText(aNodes[0]);
                    }
                  }
                }

                var video = new Object();

                video.title = title;
                video.description = description;
                video.publisher = publisher;
                video.length = "";
                video.url = unescape(lr[1]);
                video.filename = this.CleanFilename(video.title) + ".flv";

                this.AddVideo(tab.videoUrls, video);
              }
            }
          }
        }
      }
    }
  },

  ParseBreakVideos: function(tab)
  {
    var player = tab.document.getElementById("break_player");

    if (player)
    {
      var attributes = player.attributes;

      for (var i = 0; i < attributes.length; ++i)
      {
        if (attributes[i].name == "flashvars")
        {
          var pairs = attributes[i].value.split("&");

          for (var i = 0; i < pairs.length; ++i)
          {
            lr = pairs[i].split("=");

            if (lr.length == 2)
            {
              if (lr[0] == "sVidLoc")
              {
                var spans = tab.document.getElementsByTagName("span");

                title = this.CleanTitle(tab.title);

                for (var j = 0; j < spans.length; ++j)
                {
                  if (spans[j].className == "video_title")
                  {
                    title = this.CleanTitle(this.ExtractText(spans[j]));
                  }
                }

                var description = "";
                var descriptionNode = tab.document.getElementById("description_content");
                if (descriptionNode != null)
                {
                  description = this.ExtractText(descriptionNode);
                }

                var video = new Object();

                video.title = title;
                video.description = description;
                video.publisher = "";
                video.length = "";
                video.url = unescape(lr[1]);
                video.filename = this.CleanFilename(video.title) + ".flv";

                this.AddVideo(tab.videoUrls, video);
              }
            }
          }
        }
      }
    }
  },

  ParseImeemVideos: function(tab)
  {
    var objects = tab.document.getElementsByTagName("object");

    for (var i = 0; i < objects.length; ++i)
    {
      var params = objects[i].getElementsByTagName("param");

      if (params)
      {
        for (var j = 0; j < params.length; ++j)
        {
          if (params[j].name == "flashvars")
          {
            var pairs = params[j].value.split("&");

            for (var i = 0; i < pairs.length; ++i)
            {
              lr = pairs[i].split("=");

              if (lr.length == 2)
              {
                if (lr[0] == "file")
                {
                  var titleNode = tab.document.getElementById("ctl00_ContentPlaceHolder1_TitleLine");
                  var descriptionNode = tab.document.getElementById("ctl00_ContentPlaceHolder1_ctl01_MetadataPieceTwoValue");
                  var publisherNode = tab.document.getElementById("ctl00_ContentPlaceHolder1_ctl01_MetadataPieceOneValue");

                  var title = this.CleanTitle(tab.title);
                  var description = "";
                  var publsiher = "";

                  if (titleNode)
                  {
                    title = this.CleanTitle(this.ExtractText(titleNode));
                  }

                  if (descriptionNode)
                  {
                    description = this.ExtractText(descriptionNode);
                  }

                  if (publisherNode)
                  {
                    publisher = this.ExtractText(publisherNode);
                  }

                  var video = new Object();

                  video.title = title;
                  video.description = description;
                  video.publisher = publisher;
                  video.length = "";
                  video.url = unescape(lr[1]);
                  video.filename = this.CleanFilename(video.title) + ".flv";

                  this.AddVideo(tab.videoUrls, video);
                }
              }
            }
          }
        }
      }
    }
  },

  ParseDiggVideos: function(tab)
  {
    var h3s = tab.document.getElementsByTagName("h3");

    if (h3s != null)
    {
      for (var i = 0; i < h3s.length; ++i)
      {
        if (h3s[i].id != null && h3s[i].id.indexOf("title") == 0)
        {
          var aNode = h3s[i].getElementsByTagName("a");

          if (aNode != null && aNode.length == 1)
          {
            var parts = this.SplitUrl(aNode[0].href);
 
            if (this.MatchesDomain(parts.domain, "veoh.com") ||
                this.MatchesDomain(parts.domain, "youtube.com") ||
                this.MatchesDomain(parts.domain, "metacafe.com") ||
                this.MatchesDomain(parts.domain, "livevideo.com") ||
                this.MatchesDomain(parts.domain, "myspace.com") ||
                this.MatchesDomain(parts.domain, "video.google.com") ||
                this.MatchesDomain(parts.domain, "dailymotion.com") ||
                this.MatchesDomain(parts.domain, "break.com") ||
                this.MatchesDomain(parts.domain, "imeem.com"))
            {
              tab.diggUrls.push(aNode[0].href);
            }
          }
        }
      }
    }
  },

  ShowEmbeds: function(tab)
  {
    var embeds = tab.document.getElementsByTagName("object");

    if (embeds.length == 0)
      alert("NO EMBEDS");

    for (var i = 0; i < embeds.length; ++i) 
    {
      alert(embeds[i].src + " " + embeds[i].id);
    }
  },

  UpdateStats: function(tab)
  {
    var veohPanel = document.getElementById("veoh-panel2");
    var videoIcon = document.getElementById("veoh-video-image");
    var videoCount = document.getElementById("veoh-video-count");
    var videocastIcon = document.getElementById("veoh-videocast-image");
    var videocastCount = document.getElementById("veoh-videocast-count");

    veohPanel.setAttribute("onmousedown", tab.videoUrls.length + tab.videocastUrls.length > 0 ? "videofinder.onToolbarButtonCommand()" : "");
    videoIcon.src = tab.videoUrls.length > 0 ? "chrome://videofinder/skin/vp_videos_1.png" : "chrome://videofinder/skin/vp_videos_2.png";
    videoCount.setAttribute("value", tab.videoUrls.length);
    videocastIcon.src = tab.videocastUrls.length > 0 ? "chrome://videofinder/skin/vp_videocasts_1.png" : "chrome://videofinder/skin/vp_videocasts_2.png";
    videocastCount.setAttribute("value", tab.videocastUrls.length);
    videoCount.style.color = tab.videoUrls.length > 0 ? "#009bd4" : "#9c9c9c";
    videocastCount.style.color = tab.videoUrls.length > 0 ? "#009bd4" : "#9c9c9c";
  },

  StartProgress: function()
  {
    var veohImage = document.getElementById("veoh-progress-image");

    veohImage.style.visibility = "visible";
  },

  StopProgress: function()
  {
    var veohImage = document.getElementById("veoh-progress-image");

    veohImage.style.visibility = "hidden";
  }
};

var progressListener = 
{
  QueryInterface: function(iid)
  {
    if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
        iid.equals(Components.interfaces.nsISupportsWeakReference) ||
        iid.equals(Components.interfaces.nsISupports))
    {
      return this;
    }
    throw Components.results.NS_NOINTERFACE;
  },

  onLocationChange: function(progress, request, location)
  {
    if (progress.DOMWindow.parent == progress.DOMWindow)
    {
      var url = "";

      if (request)
      {
        url = request.name;
      }
       
      //logger.Log("onLocationChange isLoading: " + progress.isLoadingDocument + " url " + url);

      if (progress.isLoadingDocument)
      {
        videofinder.SetDOMWindow(progress.DOMWindow, url);
      }
      else
      {
        videofinder.SetDOMWindow(progress.DOMWindow, window._content.location.href);
        videofinder.ParseVideos(window._content.location.href);
      }

      if (typeof(url) != "string" || url.indexOf("http") < 0)
      {
        videofinder.StopProgress();
      }
    }

    return 0;
  },

  onStateChange: function(progress, request, flag, status)
  {
    //logger.Log("OnStateChange " + flag);
    if (videofinder.progressId < 0)
    {
      videofinder.StartProgress();
    }
    if (flag & Components.interfaces.nsIWebProgressListener.STATE_STOP)
    {
      var url = "";

      if (request)
      {
        url = request.name;
      }
       
      //logger.Log("onStateChange url " + url);
      videofinder.ParseVideos(url);
    }

    return 0;
  },

  onProgressChange: function(progress, request , curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress ) 
  {
    return 0;
  },

  onStatusChange: function(progress, request, status, message) 
  {
    return 0;
  },


  onSecurityChange: function(progress, request, state ) 
  {
    return 0;
  },

  onLinkIconAvailable: function(a) 
  {
    return 0;
  } 
};


window.addEventListener("load", function(e) { videofinder.onLoad(e); }, false);

