/* 
** Class to allow the easy fetching of flickr content client side
** $Id: flickrninja.js 1023 2009-07-13 08:00:29Z luke $
*/

/******************************************
********* HOW TO USE FlickrNinja **********
******************************************/
/* Step 1: Set us up the ninjabomb
** Example: var fn = new FlickrNinja('b4cb5f6367bc601ae4d192c4172360a1', '25759214@N03', 15);
*/

// var fn = new FlickrNinja('apiKey', 'userId', NUMBER_OF_PICTURES_YOU_WANT));

/* Step 2: Set up your response function.
**
** Do stuff here. 'this.pix' has all the pictures, with urls already embedded.
** You can access all the photos like this:
** - Title:                   this.pix[0].title
** - Flickr Page:             this.pix[0].pageUrl
** - Medium, direct pic:      this.pix[0].photoUrl.m
** - Small, direct pic:       this.pix[0].photoUrl.s
** - Thumbnail, direct pic:   this.pix[0].photoUrl.t
** - Large, direct pic:       this.pix[0].photoUrl.b
*/

// fn.setCallback(function() { 
//   console.log(this.pix);
// });

/* Step 3: Do a search: 
**
** Your options include:
** - getByUserId(userId)
** - getByTag([tag1, tag2])
** - getByUserName(username)
** - getByUserIdAndTag(userId, [tag1, tag2])
** - getByUserNameAndTag(username, [tag1, tag2])
*/

// fn.getByUserNameAndTag('willdayble', ['finland']);

/* Step 4: Profit! */
/* End FlickrNinja */

var FlickrNinja = new Class({

  /** mooooo */
  Implements: [Options, Events, Log],

  options: {
    'api_key':  '',
    'user_id':  '',
    'pixLimit': 10
  },

  /* constants */
  BASE_URL: 'http://www.flickr.com/services/',
  REQ_TYPE: 'rest',
  FORMAT:   'json',
  
  /* class vars */
  defaultQueryParams: new Hash({}),
  pix: [],

  /* callback */
  cb: function() {},
  
  /* setup */
  initialize: function(options){
    this.setOptions(options);
    
    this.defaultQueryParams.combine(
      new Hash({
        'format':   this.FORMAT,
        'api_key':  this.options.api_key,
        'user_id':  this.options.user_id,
        'per_page': this.options.pixLimit
      })
    );
    
    return this;
  },
  
  /* gogooggo */
  getAll: function() {

    var params = new Hash({
      'method':   'flickr.photos.search'
    });

    this.doFlickrRequest(params.combine(this.defaultQueryParams));
  },
  
  getByUserId: function(user_id) {
    var params = new Hash({
      'method':   'flickr.photos.search'
    });

    this.doFlickrRequest(params.combine(this.defaultQueryParams).set('user_id', user_id));
  },
  
  getByTag: function(tagArray, matchMode) {

    if (!$chk(matchMode)) { 
      matchMode = 'any'; 
    }
    
    var tags = tagArray.join(',');
    
    var params = new Hash({
      'method':   'flickr.photos.search',
      'tags':     tags,
      'tag_mode': matchMode
    });

    this.doFlickrRequest(params.combine(this.defaultQueryParams));
    
  },
  
  /* get by userID and by tags
  ** @param userId string giving the flickr userid (ie 12345678@N01)
  ** @param tagArray array of tags to match on
  ** @param matchMode optional string either 'all' or 'any', related to the tags to match. Default: 'any'
  */
  getByUserIdAndTag: function(userId, tagArray, matchMode) {

    if (!$chk(matchMode)) { 
      matchMode = 'any'; 
    }
    
    var tags = tagArray.join(',');
    
    var params = new Hash({
      'user_id':  userId,
      'method':   'flickr.photos.search',
      'tags':     tags,
      'tag_mode': matchMode
    });

    this.doFlickrRequest(params.combine(this.defaultQueryParams));
    
  },
  
  getByUserName: function(username) {

    var params = new Hash({
      'method': 'flickr.people.findByUsername',
      'username': username
    });
    
    new Request.JSONP({
      url: this.BASE_URL + this.REQ_TYPE + '/',
      callbackKey: 'jsoncallback',
      data: params.combine(this.defaultQueryParams),
      onComplete: this.getByUserNameCB.bind(this)
    }).send();

  },

  /* callback for getByUsername */
  getByUserNameCB: function(data, instance) {

    if (data.stat == "fail"){
      // something broke!, maybe we couldn't find the username?
      this.log("Uh oh, you broke it. Flickr says: " + data.message);
      return;
    }

    if (data.stat != "ok"){
      // something i don't know about broke, byebye....
      return;
    }

    return this.getByUser(data.user.nsid);

  },
  
  /* get by username and by tags
  ** @param username string giving the username
  ** @param tagArray array of tags to match on
  ** @param matchMode optional string either 'all' or 'any', related to the tags to match. Default: 'any'
  */
  getByUserNameAndTag: function(username, tagArray, matchMode) {

    var params = new Hash({
      'method': 'flickr.people.findByUsername',
      'username': username
    });
    
    new Request.JSONP({
      url: this.BASE_URL + this.REQ_TYPE + '/',
      callbackKey: 'jsoncallback',
      data: params.combine(this.defaultQueryParams),
      onComplete: function(data, instance) {
          this.getByUserNameAndTagCB(data, instance, tagArray, matchMode)
        }.bind(this)
    }).send();
    
  },
  
  /* callback for getByUsername */
  getByUserNameAndTagCB: function(data, instance, tagArray, matchMode) {

    if (data.stat == "fail"){
      // something broke!, maybe we couldn't find the username?
      this.log("Uh oh, you broke it. Flickr says: " + data.message);
      return;
    }

    if (data.stat != "ok"){
      // something i don't know about broke, byebye....
      return;
    }
    
    if (!$chk(matchMode)) { 
      matchMode = 'any'; 
    }
    
    var tags = tagArray.join(',');
    
    var params = new Hash({
      'user_id':  data.user.nsid,
      'method':   'flickr.photos.search',
      'tags':     tags,
      'tag_mode': matchMode
    });

    this.doFlickrRequest(params.combine(this.defaultQueryParams));

  },
  
  doFlickrRequest: function(reqData) {
    
    new Request.JSONP({
      url: this.BASE_URL + this.REQ_TYPE + '/',
      callbackKey: 'jsoncallback',
      data: reqData,
      onComplete: this.respondToPhotos.bind(this)
    }).send();
    
  },

  setCallback: function(cb) {
    this.cb = cb;
    return this;
  },

  respondToPhotos: function(data, JSONPInstance) {

    if (data.stat != "ok"){
      // something i don't know about broke, byebye....
      this.log("Flickr wasn't happy with that request...");
      return;
    }

    this.pix = data.photos.photo;
    
    this.pix.each(function(item, index) {
      item.photoUrl = new Hash({});
      item.photoUrl.m = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_m.jpg';
      item.photoUrl.s = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_s.jpg';
      item.photoUrl.t = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_t.jpg';
      item.photoUrl.b = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_b.jpg';
      item.pageUrl = 'http://www.flickr.com/photos/' + item.owner + '/' + item.id;
    }, this);

    /* run the callback, if we can */
    this.cb.attempt([], this);
  }
  
});
