/**
 * Chomp widget
 * http://www.chomp.com
 * Copyright (C) 2010 Chomp
 * 
 * Date: 3/31/2010
 */

// namespace
ChompWidget = window.ChompWidget || {};

(function() {
    if (ChompWidget && ChompWidget.quantity) {
        // to prevent re-execution if people embed the code more than once
        return;
    }
    
    // constructor
    ChompWidget = function(options) {
        if (!options) {
            options = {};
        }
        return this.init(options);
    };
    
    ChompWidget.quantity = 0;
    ChompWidget.jsonpCallback = [];
    
    var elById = function(id) {
        return document.getElementById(id);
    };
    
    var addClass = function(el, value) {
        var existingClasses = ' ' + el.className + ' ';
        if (existingClasses.indexOf(' ' + value + ' ') < 0) {
            el.className += ' ' + value;
        }
    };
    
    var removeEl = function(el) {
        try {
            el.parentNode.removeChild(el);
        }
        catch (ex) { }
    };
    
    var JSONP = function(url) {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = url;
        document.getElementsByTagName('head')[0].appendChild(script);
        return script;
    };
    
    // pass in a timestamp (in seconds), get a string for how long ago that timestamp is
    // mostly taken from jQuery timeAgo
    // http://github.com/rmm5t/jquery-timeago
    var timeAgo = function(timestamp) {
        var distance = (new Date().getTime() - (timestamp*1000));
        var seconds = distance / 1000;
        var minutes = seconds / 60;
        var hours = minutes / 60;
        var days = hours / 24;
        var years = days / 365;
        var strings = {
            seconds: "less than a minute",
            minute: "about a minute",
            minutes: "%d minutes",
            hour: "about an hour",
            hours: "about %d hours",
            day: "a day",
            days: "%d days",
            month: "about a month",
            months: "%d months",
            year: "about a year",
            years: "%d years",
            numbers: []
        };
        function substitute(string, number) {
            var value = (strings.numbers && strings.numbers[number]) || number;
            return string.replace(/%d/i, value);
        }
        var words = seconds < 45 && substitute(strings.seconds, Math.round(seconds)) ||
            seconds < 90 && substitute(strings.minute, 1) ||
            minutes < 45 && substitute(strings.minutes, Math.round(minutes)) ||
            minutes < 90 && substitute(strings.hour, 1) ||
            hours < 24 && substitute(strings.hours, Math.round(hours)) ||
            hours < 48 && substitute(strings.day, 1) ||
            days < 30 && substitute(strings.days, Math.floor(days)) ||
            days < 60 && substitute(strings.month, 1) ||
            days < 365 && substitute(strings.months, Math.floor(days / 30)) ||
            years < 2 && substitute(strings.year, 1) ||
            substitute(strings.years, Math.floor(years));
        return words + ' ago';
    };
    
    ChompWidget.prototype = (function() {
        
        var base = 'http://chomp.com/';
        
        return {
            init: function(options) {
                this._number = ++ChompWidget.quantity;
                this.config(options);
                this.user = null;
                this.el = null;
                this.jsonpScript = null;
                var that = this;
                ChompWidget.jsonpCallback['w' + this._number] = function(json) {
                    return that.jsonpCallback(json);
                };
                return this;
            },
            config: function(options) {
                this.username = options.username || null;
                this.ratings = parseInt(options.ratings) || 3;
                if (this.ratings > 5 || this.ratings < 1) {
                    this.ratings = 5;
                }
                this._default_id = !options.id;
                this.id = options.id || 'chomp-widget-' + this._number;
                this.width = parseInt(options.width) || 'auto';
                this.height = parseInt(options.height) || 'auto';
                if (this.width != 'auto' && this.width < 175) {
                    this.width = 175; // min width of 175px
                }
                if (this.height != 'auto' && this.height < 210) {
                    this.height = 210; // min height of 210px
                }
                return this;
            },
            render: function() {
                if (ChompWidget.quantity === 1) {
                    var css_href = base + 'css/widget.css';
                    var link_elements = document.getElementsByTagName('link');
                    var found = false;
                    for(var c in link_elements) {
                        if (link_elements[c].href == css_href) {
                            found = true;
                        }
                    }
                    if (!found) {
                        // insert a stylesheet
                        var css = document.createElement('link');
                        css.href = css_href;
                        css.rel = 'stylesheet';
                        css.type = 'text/css';
                        document.getElementsByTagName('head')[0].appendChild(css);   
                    }
                }
                // use (and possibly create) the parent container
                if (this._default_id) {
                    document.write('<div class="chomp-widget" id="' + this.id + '"></div>');
                }
                this.el = elById(this.id);
                if (!this.el) {
                    document.write('<div class="chomp-widget" id="' + this.id + '"></div>');
                    this.el = elById(this.id);
                } else if (!this._default_id) {
                    addClass(this.el, 'chomp-widget');
                }
                if (this.width != 'auto') {
                    this.el.style.width = this.width + 'px';
                } else {
                    this.el.style.width = 'auto';
                }
                this.el.style.padding = '0';
                this.el.style.height = 'auto';
                this.el.innerHTML = '';
                var jsonpURL = base + 'etc/jsonp?callback=' + this._number 
                + '&username=' + encodeURIComponent(this.username)
                + '&qty=' + this.ratings;
                this.jsonpScript = JSONP(jsonpURL);
                return this;
            },
            jsonpCallback: function(json) {
                if (json.user) {
                    this.user = json.user;
                } else {
                    // error finding the user
                    this.el.innerHTML = '<a href="http://www.chomp.com" style="color: darkred; font-size: 20px;">'
                    + '<img src="/img/widget/logo.gif" alt="Chomp" /></a><br />'
                    + 'There was a problem finding the user specified for this widget.';
                    if (this.width != 'auto') {
                        this.el.style.width = (this.width-20) + 'px';
                    }
                    if (this.height != 'auto') {
                        this.el.style.height = (this.height-20) + 'px';
                    }
                    this.el.style.padding = '10px';
                    removeEl(this.jsonpScript);
                    this.jsonpScript = null;
                    return;
                }
                if (!this.user.avatar_url) {
                    this.user.avatar_url = base + 'img/home/placeholder_avatar_40.png';
                } else {
                    this.user.avatar_url += '_large';
                }
                
                this.review_count = parseInt(this.user.rating_count_negative) + parseInt(this.user.rating_count_positive);
                
                var toAppend = '\
                <a href="' + this.user.profile_url + '" class="chomp-header"><span ' 
                + 'class="chomp-header-left"></span><span class="chomp-header-right"><img src="' 
                + this.user.avatar_url + '" alt="' + this.user.name 
                + (this.user.bio ? ': ' + this.user.bio : '')
                + '" /><span class="chomp-username">' + this.user.name 
                + '</span><span class="chomp-followers">' + this.user.followed_by_count
                + ' Followers</span></span></a><p class="chomp-title" />' + this.review_count + ' iPhone app reviews</p>'
                + '<div class="chomp-ratings" id="chomp-ratings-container">';
                
                var ratings = [];
                for(var c in json.ratings) {
                    ratings.push(json.ratings[c]);
                }
                if(ratings.length) {
                    var ratingsToDisplay = this.ratings;
                    for(var ratingsToDisplay = this.ratings; ratingsToDisplay > 0; ratingsToDisplay--) {
                        var recentRating = null;
                        var recentRatingIndex = null;
                        for(var c in ratings) {
                            if (recentRating == null || parseInt(ratings[c].date) > parseInt(recentRating.date)) {
                                recentRating = ratings[c];
                                recentRatingIndex = c;
                            }
                        }
                        var categories = [];
                        for(var d in json.apps[recentRating.app_id].category_ids) {
                            categories.push(json.categories[json.apps[recentRating.app_id].category_ids[d]]['name']);
                        }
                        toAppend += '<p class="chomp-rating' 
                        + (ratingsToDisplay == 1 ? ' chomp-last-rating' : '') 
                        + '"><a href="' + json.apps[recentRating.app_id].short_url_web 
                        + '"><img class="chomp-app-icon" src="'
                        + json.apps[recentRating.app_id].icon_url + '" /><span class="chomp-app-name">'
                        + json.apps[recentRating.app_id].name + '</span></a>'
                        + '<span class="chomp-rating-content"><span class="chomp-thoughts">'
                        + '<img src="' + base + 'img/widget/heart' + (recentRating.value >= 3 ? '' : '_broken') + '.gif"'
                        + ' alt="' + (recentRating.value >= 3 ? 'positive rating' : 'negative rating') + '" /> '
                        + (recentRating.comment ? '&ldquo;' + recentRating.comment + '&rdquo;' : '')
                        + '</span><span class="chomp-rating-details"><span class="chomp-time">'
                        + timeAgo(recentRating.date)
                        + '</span><span class="chomp-categories">' + categories.join(', ') + '</span></span></span></p>';
                        delete ratings[recentRatingIndex];
                    }
                }
                toAppend += '</div><p class="chomp-footer"><span class="chomp-footer-left"></span>' 
                + '<span class="chomp-footer-right-container"><span class="chomp-footer-right"><a href="' + base 
                + '" class="chomp-home">Chomp</a><a href="http://chomp.com/s/_chomp"' 
                + ' class="chomp-download">Get Chomp now</a></span></span></p>';
                
                this.el.innerHTML += toAppend;
                if (this.height != 'auto') {
                    this.el.getElementsByTagName('div')[0].style.height = ((this.height - 145) + 'px');
                }
                removeEl(this.jsonpScript);
                this.jsonpScript = null;
            },
            destroy: function() {
                if (this.el) {
                    if (this._default_id) {
                        removeEl(this.el);
                        this.el = null;
                    } else {
                        this.el.innerHTML = '';
                    }
                }
                return this;
            }
        };
    })();
})();
