
var StreamController = function (services) {
  var self = this;
  for (var i in services) {
    services[i].fetch(function () { this.show().start(); }).setController(self);
    self.list.push(services[i]);
  }

  var $c = $('#strm div.c:first'), offset = $c.offset();
  self.$status = $('#strm_status').css({
    top: offset.top,
    left: offset.left,
    width: $('#strm').width (),
    height: $c.height(),
    opacity: 0.85
  });

  $(document).keypress(function (e) {
    var s = self.$status.data('stop');
    if (typeof s == 'undefined' || s === false)
      self.stopAll();
    else
      self.startAll();
  });
};

StreamController.prototype = {
  list: [],
  $status: null,
  startAll: function () {
    for (var i in this.list) {
      this.list[i].start();
    }
    this.$status
      .fadeOut(200, function () { $(this).empty(); })
      .data('stop', false);
  },
  stopAll: function () {
    var self = this;
    for (var i in this.list) {
      this.list[i].stop();
    }
    this.$status
      .show()
      .html('<a href="#" class="medium white">Restart? &raquo;</a>')
      .data('stop', true)
      .find('a').click(function (e) { e.preventDefault();
        self.startAll();
      });
  }
};


function PicStream () {}
PicStream.prototype = {
  initialize: function () {
    this.queue = [];
    this.page = 1;
    this.depletion = false;
    this.$container = $('#' + this.containerId);
    this.$status = $('<div />').hide()
                               .attr('id', this.statusId)
                               .addClass('status')
                               .appendTo(this.$container);
    this.$loading = $('<div />').attr('id', this.loadingId)
                                .addClass('loading')
                                .html('Loading...')
                                .appendTo(this.$container);
  },
  setController: function (ctrl) {
    this.controller = ctrl; 
  },
  clicked: function (e) {
    var $t = $(this), self = e.data.obj;

    self.controller.stopAll();
/**
    $.ajax({
      type: 'POST',
      url: '/count',
      data: {
        link: $t.attr('href'),
        title: $t.attr('title'),
        thumb: $t.attr('rel')
      },
      dataType: 'json',
      success: function (o) {
        //console.log(o);
      }
    });
**/
  },
  show: function () {
    if (this.queue.length == 0) return false;

    var self = this, p = this.queue.shift();
    if (!p) return false;

    var html =
      '<div class="photo" style="display:none;">' +
      '<a href="' + p.link + '" target="_blank" title="' + p.title + '" rel="' + p.photo + '" class="photo_link">' +
      '<img src="' + p.photo + '" /></a></div>';
    self.$container
      .prepend(html)
        .find('a.photo_link').bind('click', {obj: self}, self.clicked)
        //.hover(function () { self.stop(); }, function () { self.start(); })
        .find('img:first')
          .load(function () {
            self.$loading.hide();
            $(this).closest('div').fadeIn(250);
            new Image().src = self.queue[(self.queue.length-1)].photo;
          });

    if (this.page <= 10 && (this.queue.length < this.perPage/5) && this.depletion != true)
      this.fetch();
    return this;
  },
  start: function () {
    this.$status.fadeOut(200).empty();
    var self = this;
    this.intervalId = setInterval(function () { self.show(); }, 2500);
    return this;
  },
  stop: function () {
    this.$status
      .css({backgroundColor: '#000', color: '#fff', opacity: 0.8})
      .html('STOP')
      .fadeIn(200);
    clearInterval(this.intervalId);
    return this;
  }
};


var Flickr = function (apiKey, opts) {
  this.apiKey = apiKey;

  this.containerId = 'flickr_container';
  this.statusId = 'flickr_status';
  this.loadingId = 'flickr_loading';
  this.perPage = 100;
  this.initialize();

  this.opts = opts || {};
};
Flickr.prototype = new PicStream();
Flickr.prototype.fetch = function (callback) {
  var self = this;
  var url = 'http://api.flickr.com/services/rest/?' +
            $.param($.extend({
              api_key: this.apiKey,
              format: 'json',
              method: 'flickr.photos.getRecent',
              page: this.page,
              per_page: this.perPage
            }, this.opts));

  $.getJSON(url + '&jsoncallback=?', function (obj) {
    if (!obj.photos || !obj.photos.photo) return false;
    $(obj.photos.photo).each(function (i, p) {
      self.queue.push({
        link: 'http://www.flickr.com/photos/' + p.owner + '/' + p.id + '/',
        photo: 'http://farm' + p.farm + '.static.flickr.com/' + p.server + '/' + p.id + '_' + p.secret + '_m.jpg',
        title: p.title
      });
    });
    if ($.isFunction(callback)) callback.apply(self, arguments);
  });
  this.page++;
  return this;
};

var Picasa = function () {
  this.containerId = 'picasa_container';
  this.statusId = 'picasa_status';
  this.loadingId = 'picasa_loading';
  this.perPage = 120;
  this.initialize();
};
Picasa.prototype = new PicStream();
Picasa.prototype.fetch = function (callback) {
  var self = this;
  var url = 'http://picasaweb.google.com/data/feed/api/featured?' +
    'alt=json&' +
    'start-index=' + ((this.page*this.perPage)+1) + '&' + 
    'max-results=' + this.perPage + '&' +
    'orderby=published&' +
    'callback=?';
  $.getJSON(url, function (obj) {
    if (!obj.feed.entry) return false;
    $(obj.feed.entry).each(function (i, p) {
      self.queue.push({
        link: p.link[2].href,
        photo: p.media$group.media$thumbnail[2].url,
        title: p.title.$t
      });
    });
    if ($.isFunction(callback)) callback.apply(self, arguments);
  });
  this.page++;
  return this;
};


var Instagram = function (clientId, endPoint, opts) {
  this.clientId = clientId;
  this.endPoint = endPoint;
  this.nextMinId = '0';

  this.containerId = 'instagram_container';
  this.statusId = 'instagram_status';
  this.loadingId = 'instagram_loading';
  this.perPage = 100;
  this.initialize();

  this.opts = opts || {};
};
Instagram.prototype = new PicStream();
Instagram.prototype.fetch = function (callback) {
  var self = this;
  var url = 'https://api.instagram.com/v1' + this.endPoint +
            '?' + $.param($.extend({client_id: this.clientId, next_min_id: this.nextMinId}, this.opts));
  $.getJSON(url + '&callback=?', function (obj) {
    console.log(obj);
    if (!obj.data || !obj.pagination) return false;
    this.nextMinId = obj.pagination.next_min_id;
    $(obj.data).each(function (i, p) {
      self.queue.push({
        link: p.link,
        photo: p.images.thumbnail.url,
        title: p.caption.text
      });
    });
    if ($.isFunction(callback)) callback.apply(self, arguments);
  });
  this.page++;
  return this;
};

var TwitPic = function () {
  this.containerId = 'twitpic_container';
  this.statusId = 'twitpic_status';
  this.loadingId = 'twitpic_loading';
  this.perPage = 100;
  this.initialize();
};
TwitPic.prototype = new PicStream();
TwitPic.prototype.fetch = function (callback) {
  var self = this;
  var url = 'http://search.twitter.com/search.json?' +
    'q=' + encodeURIComponent('twitpic') + '&' +
    'page=' + this.page + '&' + 
    'rpp=' + this.perPage + '&' +   
    'callback=?';
  $.getJSON(url, function (obj) {
    if (!obj.results) return false;
    $(obj.results).each(function (i, p) {
      var m = p.text.match(/http:\/\/twitpic\.com\/(\w+)/);
      if (!m) return;
      self.queue.push({
        link: 'http://twitpic.com/' + m[1],
        photo: 'http://twitpic.com/show/thumb/' + m[1],
        title: p.text
      });
    });
    if ($.isFunction(callback)) callback.apply(self, arguments);
  });
  this.page++;
  return this;
};


var TweetPhoto = function () {
  this.apiKey = '8f9be868-cf13-4142-8444-0023362bf29f';
  this.containerId = 'tweetphoto_container';
  this.statusId = 'tweetphoto_status';
  this.loadingId = 'tweetphoto_loading';
  this.perPage = 100;
  this.initialize();
};
TweetPhoto.prototype = new PicStream();
TweetPhoto.prototype.fetch = function (callback) {
  var self = this;
  var url = 'http://tweetphotoapi.com/api/tpapi.svc/jsonp/socialfeed?' +
    'ps=' + this.perPage + '&' +
    'callback=?';
  $.getJSON(url, function (obj) {
    if (!obj.List) return false;
    $(obj.List).each(function (i, p) {
      self.queue.push({
        link: 'http://tweetphoto.com/' + p.PhotoId,
        photo: p.ImageThumbnail,
        title: p.Content || ''
      });
    });
    if ($.isFunction(callback)) callback.apply(self, arguments);
  });
  this.page++;
  return this;
};



var Custom = function (username, service, label, perPage) {
  this.username = username;
  this.service = service;
  this.containerId = label + '_container';
  this.statusId = label + '_status';
  this.loadingId = label + '_loading';
  this.perPage = perPage || 100;
  this.initialize();
};
Custom.prototype = new PicStream();
Custom.prototype.fetch = function (callback) {
  var self = this;

  if (self.depletion === true) return false;

  var url = '/api/photos?' +
    'username=' + this.username + '&' +
    'service=' + this.service + '&' +
    'page=' + this.page + '&' +
    'per_page=' + this.perPage + '&' +
    'callback=?';
  $.getJSON(url, function (obj) {
    if (!obj.status) return false;
    if (obj.photos.length == 0) {
      self.depletion = true;
      return false;
    }

    if (obj.status == 'success') {
      $(obj.photos).each(function(i, p) {
        self.queue.push({
          link: p.link,
          photo: p.thumb,
          title: p.title
        });
      });
      if ($.isFunction(callback)) callback.apply(self, arguments);
    }
  });
  this.page++;
  return this;
};



