/*****************************************
 * Flickr Browser (in jQuery)
 * version: 0.1 (03/01/2011)
 * written for jQuery 1.4.1
 * by Oksana Timonin www.oneapart.com
 * for Triple Aught Design www.tripleaughtdesign.com
 *****************************************/
(function ($) {
    w = false;
    var e;
    var c = [];
    var o = {};
    var types = {
        "recent": 'flickr.people.getPublicPhotos',
        "context": 'flickr.photos.getAllContexts',
        "photoset": 'flickr.photosets.getPhotos'
    };
    var map = {};
    var bank = {
        method: "recent",
        page: 0,
        pages: 0,
        perpage: 0,
        photos: [],
        total: 0
    };
    var methods = {
        createHash: function () {
            var i;
            for (i = 0; i < bank.photos[bank.page].length; i++) {
                map[bank.photos[bank.page][i]["id"]] = {
                    page: bank.page,
                    index: i
                };
            }
        },
        get: function (type, settings) {
            //console.log("performing get: ", type, "; page: ", settings.page);
            var self = this,
                photos = {},
                tmp, i;
            if (type !== "context") { // we are getting a list of photos
                w = true;
                if (type !== bank.method || (type === "photoset" && bank.id !== settings.photoset_id)) {
                    bank.photos = [];
                    map = {};
                    type = (!type) ? "recent" : type;
                }
                $.getJSON(self.url(types[type], settings), function (data) {
                    if (data.stat === "ok") {
                        tmp = (data.photos) ? data.photos : data.photoset;
                        bank.photos[tmp.page] = tmp.photo;
                        bank = $.extend(bank, tmp);
                        bank.photo = null;
                        bank.method = type;
                    }
                    w = false;
                    self.createHash();
                });
            } else { // we are assuming that there is a list of photos to get context for already
                if (bank.photos[bank.page] !== null) { // but we can't trust ourselves, so we'll check
                    for (i = 0; i < bank.photos[bank.page].length; i++) {
                        if (bank.photos[bank.page][i].id === settings.photo_id) {
                            if (!bank.photos[bank.page][i].sets) {
                                $.getJSON(self.url(types[type], settings), function (data) {
                                    if (data.set && data.set.length > 0) {
                                        self.update(settings.photo_id, data.set);
                                    }
                                });
                            } else {
                                self.update(settings.photo_id, bank.photos[bank.page][i].sets);
                            }
                        }
                    }
                }
            }
        },
        wait: function (f) {
            var args = arguments,
                interval = "";
            if (!f || typeof (f) !== "function") {
                return;
            }
            function exe() {
                var i;
                for (i = 1; i < args.length; i++) {
                    if (window['w'] === true) {
                        if (interval === "") {
                            interval = setInterval(arguments.callee, 500);
                        }
                        return;
                    } else {
                        clearInterval(interval);
                        interval = "";
                        if (f && typeof (f) === "function") {
                            f();
                        }
                    }
                }
            }
            exe();
        },
        update: function (id, data) {
            var i, s, item, info, container, text;
            //        console.log("performing bank update:", id, data);
            for (i = 0; i < bank.photos[bank.page].length; i++) {
                if (bank.photos[bank.page][i].id === id && !bank.photos[bank.page][i].sets) {
                    bank.photos[bank.page][i].sets = data;
                }
            }
            // console.log("performing view update:", id, data);
            item = e.find('#p' + id);
            info = item.children('.info');
            container = info.children('.appearsin');
            for (i = 0; i < bank.photos[bank.page].length; i++) {
                text = ['This photo is in'];
                for (s = 0; s < data.length; s++) {
                    if (data[s].id !== o.photoset_id) {
                        if (s === data.length - 1) {
                            text.push('<a href="#' + data[s].id + '">' + data[s].title + '</a>');
                        } else {
                            text.push('<a href="#' + data[s].id + '">' + data[s].title + '</a>,');
                        }
                    }
                }
            }
            if (text.length > 1) {
                container.html(text.join(' '));
            }
        },
        init: function (obj, settings) {
            var self = this,
                collections;
            // console.log("performing init:", obj, settings);
            e = obj;
            o = $.extend({}, settings);
            o.photoset_name = "Most Recent Photos";
            var b = $('<div class="browse" />').hide();
            var v = $('<div class="view" />').hide();
            var w = $('<div class="wait" />');
            e.append(b);
            e.append(v);
            e.append(w);
            e.bind('click', function (event) {
                if ($(event.target).is('a')) {
                    if ($(event.target).parents('.browse').length > 0) {
                        $(event.target).parents('.browse').find('li').removeClass('active');
                        $(event.target).parent('li').addClass('active');
                        if ($(event.target).attr('href').split('#')[1] === "recent") {
                            o.photoset_id = '';
														o.photoset_name = "Most Recent Photos";
                            self.get("recent", o);
                        } else {
                            o.photoset_id = $(event.target).attr('href').split('#')[1];
                            o.photoset_name = $(event.target).html();
                            self.get("photoset", o);
                        }
                        self.wait(function () {
                            self.list(1)
                        }, "w")
                    } else if ($(event.target).parents('.list').length > 0) {
                        e.find('.pages').animate({
                            bottom: '-48px'
                        });
                        e.find('.carousel').slideDown();
                        e.find('.list').slideUp();
                        o.photo_id = $(event.target).attr('href').split('#')[1];
                        self.get("context", o);
                        self.view(o.photo_id);
                    } else if ($(event.target).parents('.carousel').length > 0) {
                        if ($(event.target).hasClass('close')) {
                            e.find('.carousel').slideUp();
														e.find('.carousel ul').html("");
                            e.find('.pages').animate({
                                bottom: '0'
                            });
                            e.find('.list').slideDown();
                        } else if ($(event.target).hasClass('prev') || $(event.target).hasClass('next')) {
													if ($(event.target).hasClass('prev')) {
                            o.photo_id = e.find('.carousel li').eq($('.carousel').data('scrollable').getIndex() - 1).attr('id').substr(1);
													} else if ($(event.target).hasClass('next')) {
                            o.photo_id = e.find('.carousel li').eq($('.carousel').data('scrollable').getIndex() + 1).attr('id').substr(1);
													}
                          self.get("context", o);
                          self.view(o.photo_id);
                        } else if ($(event.target).parent().hasClass('appearsin')) {
                            o.photoset_id = $(event.target).attr('href').split('#')[1];
                            o.photoset_name = $(event.target).html();
                            self.get("photoset", o);
                            self.wait(function () {
                                self.list(1)
                            }, "w")
                        } else if ($(event.target).parent().hasClass('description')) {
													window.open($(event.target).attr("href"), '_blank');
                        } else if ($(event.target).hasClass('fullscreen')) {
													$(event.target).toggleClass('waiting');
													$('<img style="margin:15px" />').load(function () {
														var img = $(this);
														img.css({"max-height" : ($(window).height() - 70) + "px", "max-width" : ($(window).width() - 70) + "px"});
														img.modal({
														maxHeight : $(window).height() - 40,
														maxWidth : $(window).width() - 40,
														overlayClose : true,
														autoResize : true,
														autoPosition : true
														});
														$(event.target).toggleClass('waiting');
													}).attr('src', $(event.target).parents("li").children(".img").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, "").replace('.jpg', '_b.jpg') + "?" + Math.floor(Math.random() * 1001));
												}
                    } else if ($(event.target).parents('.pages').length > 0) {
                        var num = $(event.target).attr('href').split('#')[1];
                        self.list(num)
                    }
                }
                return false;
            });
            return e.each(function () {
                $.getJSON(self.url('flickr.collections.getTree', o), function (data) {
                    collections = data.collections.collection;
                    self.navigation(collections);
                });
                self.list(1);
                self.callback.call(this);
            });
        },
        url: function (method, params) {
            return 'http://api.flickr.com/services/rest/?method=' + method + '&format=json' + '&api_key=' + ($.isEmpty(params) ? '' : '&' + $.param(params)) + '&jsoncallback=?';
        },
        navigation: function (data) {
            //        console.log("building navigation from", data);
            var c = 0,
								cc = 0,
                sets = [],
                s = 0,
                collections = data;
            var render = e.children('.browse');
            var content = ['<ul>', '<li class="header">Gallery</li>'];
            if (typeof(collections) !== "undefined") {
                content.push('<li class="active"><a href="#recent">Most Recent</a></li>');
                for (c = 0; c < collections.length; c++) {
									sets = [];
									if (typeof(collections[c].set) !== "undefined") {
                    for (s = 0; s < collections[c].set.length; s++) {
                        sets.push('<li><a href="#' + collections[c].set[s].id + '">' + collections[c].set[s].title + '</a></li>');
                    }
									} else if (typeof(collections[c].collection) !== "undefined"){
                    for (cc = 0; cc < collections[c].collection.length; cc++) {
                      sets.push('<li class="subtitle">' + collections[c].collection[cc].title + ':</li>');
											if (typeof(collections[c].collection[cc].set) !== "undefined") {
												for (s = 0; s < collections[c].collection[cc].set.length; s++) {
													sets.push('<li class="secondary"><a href="#' + collections[c].collection[cc].set[s].id + '">' + collections[c].collection[cc].set[s].title + '</a></li>');
												}
											}
                    } 
									}
                  content.push('<li><div class="title">' + collections[c].title + '</div><ul>' + sets.join('\n') + '</ul></li>');
                }
            } else {
              content.push('<li class="empty">There are no sets or <br/> collections.</li>');
            }
            content.push('</ul>');
            render.append(content.join('\n')).show();
        },
        view: function (id) {
            var self = this,
                content = [],
                render = e.find('.carousel ul'),
                tmp = [],
                i, photos = [],
                left, right, current;
            if (map[id].index - o.view <= 0 && map[id].page >= 2) {
                if (typeof (bank.photos[map[id].page - 1]) === "undefined") {
                    o.page = map[id].page - 1;
                    self.get(bank.method, o);
                    self.wait(function () {
                        self.view(id)
                    }, "w");
										return;
                };
                tmp = bank.photos[map[id].page - 1].concat(bank.photos[map[id].page]);
                left = map[id].index - o.view + bank.photos[map[id].page - 1].length;
                right = map[id].index + o.view + 1 + bank.photos[map[id].page - 1].length;
            } else if (map[id].index + o.view > bank.photos[map[id].page].length - 1 && map[id].page < bank.pages) {
                if (typeof(bank.photos[map[id].page + 1]) === "undefined") {
                    o.page = map[id].page + 1;
                    self.get(bank.method, o);
                    self.wait(function () {
                        self.view(id)
                    }, "w");
										return;
                };
                tmp = bank.photos[map[id].page].concat(bank.photos[map[id].page + 1]);
                left = map[id].index - o.view;
                right = map[id].index + o.view + 1;
            } else {
                tmp = bank.photos[map[id].page].slice();
                left = Math.max((map[id].index - o.view), 0), right = Math.min((map[id].index + o.view + 1), (bank.photos[map[id].page].length));
            }
            if (render.children().length > 0) {
              current = map[render.find(".current").attr('id').split("p")[1]];
              if ((current.index === 0 && map[id].index > current.index) || map[id].index < current.index) {
                photos[0] = tmp[left];
              } else if ((current.index === bank.photos[current.page].length && map[id].index < current.index) || map[id].index > current.index) {
                photos[0] = tmp[right - 1];
              }
            } else {
              photos = tmp.slice(left, right);
            }
						if (typeof(photos) !== "undefined") {
            for (i = 0; i < photos.length; i++) {
							if (render.children("#p" + photos[i].id).length <= 0) {
                if (photos[i].id == id) {
                    content.push('<li id="p' + photos[i].id + '" class="current"><div class="img"></div><div class="info"><a class="fullscreen" href="#fullscreen"><img src="images/bg_process.gif" /></a><div class="title">' + photos[i].title + '</div><div class="description">' + photos[i].description._content + '</div><div class="appearsin"/></div></li>');
                } else {
                    content.push('<li id="p' + photos[i].id + '"><div class="img"></div><div class="info"><a class="fullscreen" href="#fullscreen"><img src="images/bg_process.gif" /></a><div class="title">' + photos[i].title + '</div><div class="description">' + photos[i].description._content + '</div><div class="appearsin"/></div></li>');
                }
                self.preload('p' + photos[i].id, 'http://farm' + photos[i].farm + '.static.flickr.com/' + photos[i].server + '/' + photos[i].id + '_' + photos[i].secret + '.jpg')
							}
            }
						}
            if (render.children().length > 0) {
                if ((current.index === 0 && map[id].index > current.index) || map[id].index < current.index) {
									if (content.length > 0) {
										$('.carousel').data('scrollable').addItemBefore(content.join('\n'));
									} else {
										$('.carousel').data('scrollable').seekTo(e.find('#p' + id).index(), 500)
									}
                } else if ((current.index === bank.photos[current.page].length && map[id].index < current.index) || map[id].index > current.index) {
						      $('.carousel').data('scrollable').seekTo(e.find('#p' + id).index(), 500).addItem(content.join('\n'))
                }
            } else {
              render.append(content.join('\n'));
							render.children('li').show();
							$('.carousel').scrollable({
									speed: 500,
									keyboard: false,
									easing: 'linear',
									items: 'ul',
									prev: ".prev",
									next: ".next",
									disabledClass: "disabled",
									vertical: false,
									circular: false,
									initialIndex: 0
							});
							$('.carousel').data('scrollable').seekTo(e.find('#p' + id).index(), 0)
            }
            e.find('#p' + id).addClass('current').animate({opacity: 1}).children(' .info').animate({
                height: '10em'
            });
            e.find('#p' + id).siblings('li').removeClass('current').animate({opacity: 0.5}).children('.info').animate({
                height: '30px'
            });
        },
        list: function (page) {
            var self = this,
                temp = [],
                photos = [],
                i, a, content, t = [],
                l = [];
            var p = (page === 'undefined') ? 1 : page;
            var items_range = [o.list * (p - 1) + 1, o.list * p];
            var pages_range = [Math.ceil(items_range[0] / o.per_page), Math.ceil(items_range[1] / o.per_page)];
            var in_page_range = [items_range[0] - (pages_range[0] - 1) * o.per_page - 1, items_range[1] - (pages_range[0] - 1) * o.per_page];
            if (pages_range[0] === pages_range[1]) {
                if (typeof (bank.photos[pages_range[0]]) === "undefined") {
                    o.page = pages_range[0]
                    self.get(bank.method, o);
                    self.wait(function () {
                        self.list(p)
                    }, "w");
                } else {
                    photos = bank.photos[pages_range[0]].slice(in_page_range[0], in_page_range[1]);
                }
            } else {
                if (typeof (bank.photos[pages_range[0]]) === "undefined" || typeof (bank.photos[pages_range[1]]) === "undefined") {
                    for (a = 0; a < pages_range.length; a++) {
                        if (typeof (bank.photos[pages_range[a]]) === "undefined") {
                            o.page = pages_range[a];
                            self.get(bank.method, o);
                            self.wait(function () {
                                self.list(p)
                            }, "w");
                        }
                    }
                } else {
                    temp = bank.photos[pages_range[0]].concat(bank.photos[pages_range[1]]);
                    photos = temp.slice(in_page_range[0], in_page_range[1]);
                }
            }
            var render = e.children('.view');
            var thumbs = ['<div class="header">' + o.photoset_name + '</div>', '<div class="list">', '<ul>'];
            var large = ['<div class="carousel">', '<a class="close" href="#">x</a>', '<ul>'];
            if (photos.length > 0) {
                for (i = 0; i < photos.length; i++) {
                    thumbs.push('<li id="t' + photos[i].id + '"><div class="img"><a href="#' + photos[i].id + '"></a></div><div class="title"><a href="#' + photos[i].id + '">' + photos[i].title + '</a></div></li>');
                    t.push(['t' + photos[i].id, 'http://farm' + photos[i].farm + '.static.flickr.com/' + photos[i].server + '/' + photos[i].id + '_' + photos[i].secret + '_m.jpg']);
                    self.preload('t' + photos[i].id, 'http://farm' + photos[i].farm + '.static.flickr.com/' + photos[i].server + '/' + photos[i].id + '_' + photos[i].secret + '_m.jpg');
                }
            }
            thumbs.push('</ul>', '</div>');
            large.push('</ul>', '<a class="prev" href="#"></a>', '<a class="next" href="#"></a>', '</div>');
            content = thumbs.concat(large);
            render.html(content.join('\n'));
            render.append(self.pagination(p)).show();
            $('.wait').hide();
        },
        pagination: function (current, total) {
            var i, li;
            var c = (current) ? Number(current) : 1;
            var t = Math.ceil(Number(bank.total) / o.list);
            if (t > 1) {
							var left = Math.max(Math.min(c - 2, t - 2), 1);
							var right = (c + 2 >= t - 1) ? t : c + 2;
							var render = $('<div class="pages" />');
							var pages = ['<ul>'];
              if (c > 1) {
                pages.push('<li class="prev"><a href="#' + (c - 1) + '">Prev</a></li>');
              } else {
              	pages.push('<li class="prev"><span>Prev</span></li>');
              }
							if (t > 7) {
                if (left > 0) {
                  for (i = 1; i < Math.min(3, left); i++) {
                  	li = (i === c) ? '<li class="current"><span>' + i + '</span></li>' : '<li><a href="#' + i + '">' + i + '</a></li>';
                    pages.push(li);
                  }
                  if (2 < left) {
                    pages.push("<li><span>...</span></li>");
                  }
                }
                for (i = left; i <= Math.min(right, t); i++) {
                  li = (i === c) ? '<li class="current"><span>' + i + '</span></li>' : '<li><a href="#' + i + '">' + i + '</a></li>';
                  pages.push(li);
                }
								if (t - 2 > c + 2) {
	                	pages.push("<li><span>...</span></li>");
								}
	              if (t - 1 > c + 2) {
               	  for (i = t - 1; i <= t; i++) {
                		li = (i === c) ? '<li class="current"><span>' + i + '</span></li>' : '<li><a href="#' + i + '">' + i + '</a></li>';
                  	pages.push(li);
                	}
                }
								} else {
									for (i = 1; i <= t; i++) {
										li = (i === c) ? '<li class="current"><span>' + i + '</span></li>' : '<li><a href="#' + i + '">' + i + '</a></li>';
										pages.push(li);
									}
								}
                if (c < t) {
                    pages.push('<li class="next"><a href="#' + (c + 1) + '">Next</a></li>');
                } else {
                    pages.push('<li class="next"><span>Next</span></li>');
                }
                pages.push('</ul>');
                render.append(pages.join('\n'));
                return render;
            } else {
                return;
            }
        },
        preload: function (id, src) {
            $('<img />').load(function () {
                $('li#' + id + ' .img').css({
                    'background-image': 'url(' + src + ')'
                }).hide().fadeIn();
                $('li#' + id + ' .title').fadeIn();
            }).attr('src', src + "?" + Math.floor(Math.random() * 1001));
        },
        callback: function () {}
    };
    // the plugin
    $.extend({
        isEmpty: function (obj) {
            var i;
            for (i in obj) {
                return false;
            }
            return true;
        }
    });
    $.fn.endless = function (options) {
        var settings = {
            api_key: '',
            user_id: '',
            photo_id: '',
            per_page: 500,
            list: 9,
            view: 2,
            extras: 'description',
            media: 'photos',
            content_type: 'photos',
            page: ''
        };

        return this.each(function () {
            if (options) {
                $.extend(settings, options);
            }
            var obj = $(this);
            methods.init(obj, settings);
        });
    };
})(jQuery);
