String.prototype.leftPad = function (l, c) { return new Array(l - this.length + 1).join(c || '0') + this; }
Math.frac = function(v) { return v - Math.floor(v); }

// global singleton, don't duplicate widget!
co2m_widget = null;

function CO2monitorWidget(widget) {

    // store additional reference to myself
    // the signal handlers need it, because "this" will be reassigned by jQuery
    var self = this;

    this.widget = widget;

    this.dayFraction = function() {
        return (new Date() - this.day_start) / (86400 * 1000);
    }

    this.yearFraction = function() {
        return (new Date() - this.year_start) / (365.25 * 86400 * 1000);
    }

    this.getTextObject = function(text, css) {
        var o = $('<div class="text"></div>');
        o.html(text);
        if (css)
            o.css(css);

        return o;
    }

    this.loadFromServer = function(callback) {
        $.getJSON('/ajax/widget/', function(data) {
            self.init(data);

            if (callback)
                callback.apply(self);
        });
    }

    // counter panel
    this.activateCounter = function(panel) {
        if (!this.counterObjects)
            this.createCounter(panel);
        this.counterIntervalHandler();
        this.counterInterval = setInterval(this.counterIntervalHandler, 1000);
    }

    this.deactivateCounter = function() {
        clearInterval(this.counterInterval);
    }

    this.createCounter = function(widget_body) {
        var my_digits = [];
        var gl_digits = [];

        function createDigit(x, y) {
            var img = $('<img>');
            img.attr('src', '/media/images/widget/co2-monitor-widget_box-trans.png');
            img.css('position', 'absolute');
            img.css('left', x + 'px');
            img.css('top', y + 'px');
            img.css('background', 'url(/media/images/widget/co2-monitor-widget_numbers.jpg)');
            return img;
        }

        for(var i=0; i<5; i++) {
            var img = createDigit(23 + i * 18, 40);
            widget_body.append(img);
            my_digits.push(img);

            var img = createDigit(23 + i * 18, 125);
            widget_body.append(img);
            gl_digits.push(img);
        }

        for(var i=0; i<3; i++) {
            var img = createDigit(117 + i * 18, 40);
            widget_body.append(img);
            my_digits.push(img);

            var img = createDigit(117 + i * 18, 125);
            widget_body.append(img);
            gl_digits.push(img);
        }

        var timer = this.getTextObject('', {top:179, left:4, color:'#fff'});
        widget_body.append(timer);

        widget_body.append(this.getTextObject(gettext('My CO<sub>2</sub> emissions'), {top:19, left:6}));
        widget_body.append(this.getTextObject(gettext('Country average'), {top:106, left:6}));

        var thisyear = this.getTextObject('', {top:78, left:4, color:'#fff'});

        widget_body.append(thisyear);
        widget_body.append(this.getTextObject('kg', {top:48, left:171, width:20}));
        widget_body.append(this.getTextObject('kg', {top:133, left:171, width:20}));

        this.counterObjects = {
            timer: timer,
            my_digits: my_digits,
            gl_digits: gl_digits,
            thisyear: thisyear
        }
    }

    this.counterIntervalHandler = function() {
        self.counterObjects.timer.text(getDateString());
        self.counterObjects.thisyear.html(
            self.year + ' | ' + parseInt(self.emissions_thisyear) + ' kg CO<sub>2</sub>');
        setDigits(self.counterObjects.my_digits, self.emissions_thisyear_until_today + self.dayFraction() * self.emissions_today);
        setDigits(self.counterObjects.gl_digits, self.yearFraction() * self.emissions_average);
    }


    // thermometer
    this.activateThermometer = function(panel) {
        if (this.thermometerObjects)
            return;

        var to = function(top) {
            return {top: top, left: 0, width: 185, textAlign: 'right'};
        };

        panel.append(this.getTextObject(gettext('My commitments'), to(10)));
        panel.append(this.getTextObject(gettext('Next 12 months') + ': ' + this.measures_planned, to(32)));
        panel.append(this.getTextObject(gettext('Fulfilled') + ': ' + this.measures_realized, to(48)));

        panel.append(this.getTextObject(parseInt(this.measures_planned_emissions) + ' kg CO<sub>2</sub>', {
            top: 101, left: 0, width: 185, textAlign: 'right'}));

        panel.append(this.getTextObject(this.year + ': ' + parseInt(this.emissions_thisyear) + ' kg CO<sub>2</sub>', {
            top: 172, left: 6, color: '#fff'}));

        withCommitments = parseInt(this.emissions_thisyear - this.measures_planned_emissions);
        panel.append(this.getTextObject(gettext('With commitments') + ': ' + Math.max(withCommitments, 0) + ' kg', {
            top: 192, left: 6, color: '#bfb'}));


        this.thermometerObjects = true;
    }


    // thermometer
    this.activateGroup = function(panel) {
        if (this.groupObjects)
            return;

        var to = function(top, color) {
            var css = {top: top, left: 6};
            if (color)
                css.color = color;
            return css
        };

        panel.append(this.getTextObject(gettext('Total users'), to(45)));
        panel.append(this.getTextObject('' + parseInt(this.group_users), to(73, '#fff')));

        panel.append(this.getTextObject(gettext('Emissions') + ' - ' + gettext('median'), to(103)));
        panel.append(this.getTextObject(parseInt(this.group_emissions_median) + ' kg CO<sub>2</sub>', to(131, '#fff')));

        panel.append(this.getTextObject(gettext('Savings commitment all users'), to(161)));
        panel.append(this.getTextObject(parseInt(this.group_measures_emissions / 1000.0) + ' t CO<sub>2</sub>', to(189, '#fff')));

        this.groupObjects = true;
    }

    // facebook
    this.activateFacebook = function(panel) {
        if (this.facebookObjects)
            return;

        panel.append('' +
			'<div id="facebook-panel">' +
            '<div id="facebook-status-panel"><strong>Facebook</strong><br /><br/>' +
            '<a href="#" id="co2-facebook-connect-button"> \
            <img id="fb_login_image" src="http://static.ak.fbcdn.net/images/fbconnect/login-buttons/connect_light_medium_long.gif" alt="Connect" /></a>' +
			'<br/><br/></div>' +
			'<div id="facebook-action-panel"></div></div>' +
			'');
        if(!this.user_authorized)
            $('#facebook-status-panel', panel).append(gettext('Please <a href="/en/account/login/">login</a> to connect your profile with facebook!'));
        var fb_api_key = self.fb_api_key;
		$('a#co2-facebook-connect-button',panel).click(function() {
			FB_RequireFeatures(["Api","XFBML"], function(){
		        FB.init(fb_api_key, "/fbconnect/xdreceiver.htm");
				FB.XFBML.Host.autoParseDomTree = false;
                api = FB.Facebook.apiClient;
                FB.Connect.requireSession(function(){
    				uid = api.get_session().uid;
    				fields = new Array('name');
                    $('div#facebook-status-panel').html('Connected!');
      				api.users_getInfo([api.get_session().uid],["first_name", "last_name", "locale"],function(result, exception){
    	            	$('div#facebook-status-panel').html('Hello' + ' ' + result[0].first_name + ' ' + result[0].last_name);
    	            });

    				jQuery.post('/fbconnect/connected/' + api.get_session().uid  + '/?session_key=' + api.get_session().session_key, {
                        csrfmiddlewaretoken: $('#csrftoken input').val()
    				}, function(){
                        FB.Connect.showAddSectionButton("profile", document.getElementById("facebook-action-panel"));
                        //user_link = new FB.XFBML.ProfilePic(document.getElementById('facebook-status-panel'));
                        //FB.XFBML.Host.addElement(user_link);
                        //FB.XFBML.Host.parseDomTree();
    				});
                });
			});
		});

        this.facebookObjects = true;
    }

    // info
    this.activateInfo = function(panel) {
        if (this.infoObjects)
            return;

        panel.append('<div class="info">' +
            '<strong>About</strong><br />' +
            'This widget presents you a summary ' +
            'of your CO<sub>2</sub>-monitor account ' +
            'information and statistics.<br /><br />' +
            'You will be able to share this widget ' +
            'on Facebook or embed it on your personal' +
            ' web page</div>');

        this.infoObjects = true;
    }


    // face
    this.faceTexts = ['Very happy', 'Happy', 'Pleased', 'Patient', 'Annoyed', 'Angry', 'Sick'];
    this.activateFace = function(panel) {
        if (!this.faceObjects) {
            this.faceObjects = {};

            this.faceObjects.mood = this.getTextObject('', {top: 22, left: 6, color: '#fff'});
            panel.append(this.faceObjects.mood);

            panel.append(this.getTextObject('The World is:', {top: 6, left: 6}));
        }

        panel.css('background', 'url(/media/images/widget/co2m-widget-back-world' + this.earth_face + '.jpg)');
        this.faceObjects.mood.html(this.faceTexts[this.earth_face]);
    }


    // internal stuff
    this.panels = {
        counter: [this.activateCounter, this.deactivateCounter],
        thermo: [this.activateThermometer, null],
        group: [this.activateGroup, null],
        face: [this.activateFace, null],
        facebook: [this.activateFacebook, null],
        info: [this.activateInfo, null]
    };
    this.currentPanel = '';

    this.activatePanel = function(name) {

        if (this.currentPanel == name)
            return;

        var newPanel = self.widget.find('#b-' + name);

        if (!newPanel.length) {
            name = 'counter';
            newPanel = self.widget.find('#b-counter');
        }

        function initNewPanel() {
          if (self.panels[self.currentPanel] && self.panels[self.currentPanel][1])
            self.panels[self.currentPanel][1].apply(self, [newPanel]);

          self.currentPanel = name;
          self.widget.removeClass('face counter thermo group facebook info').addClass(self.currentPanel);
          self.widget.find('.nav a').removeClass('active');
          self.widget.find('#n-'+name).addClass('active');

          if (self.panels[self.currentPanel] && self.panels[self.currentPanel][0])
              self.panels[self.currentPanel][0].apply(self, [newPanel]);

        }

        var activePanels = self.widget.find('div.body:visible, div.body.minimized');


        if (activePanels.size() > 0) {
            var timeout = BrowserDetect.browser == 'Safari' ? 0 : 200;

            self.hidePanel(activePanels);
            setTimeout(function () {
                initNewPanel();
                self.showPanel(newPanel);
            }, timeout);
        } else {
            initNewPanel();
            newPanel.show();
        }

        $.cookie('co2m_widget_panel', name, {path: '/', expires: 365});
    }

    this.showPanel = function(panel, callback) {
        if (BrowserDetect.browser == 'Safari') {
            panel.show(callback);
        } else {
            panel.slideDown(200, callback);
        }
    }

    this.hidePanel = function (panel, callback) {
        if (BrowserDetect.browser == 'Safari') {
            panel.hide(callback);
        } else {
            panel.slideUp(200, callback);
        }
    }

    this.navClickHandler = function() {
    	widget = $('#widget');
    	var panel_id = this.id.substr(2);

    	if (widget.hasClass(panel_id)) {
    		panel = $('#b-' + panel_id);
    		if (!panel.hasClass('minimized')) {
    		    self.hidePanel(panel);
    			panel.addClass('minimized');
    		} else {
    			self.showPanel(panel);
    			panel.removeClass('minimized');
    		}
    	} else {
        	self.activatePanel(this.id.substr(2));
		}
        return false;
    }

    this.init = function(data) {

        // these variables will be set at least partially from the outside
        this.year = data.year;
        this.emissions_thisyear = data.emissions_thisyear;
        this.emissions_thisyear_until_today = data.emissions_thisyear_until_today;
        this.emissions_today = data.emissions_today;
        this.emissions_lastyear = data.emissions_lastyear;
        this.emissions_average = data.emissions_average;

        this.measures_planned = data.measures_planned;
        this.measures_realized = data.measures_realized;
        this.measures_emissions = data.measures_emissions;
        this. measures_planned_emissions = data.measures_planned_emissions;

        this.group_users = data.group_users;
        this.group_emissions_median = data.group_emissions_median;
        this.group_measures_emissions = data.group_measures_emissions;

        this.earth_face = data.earth_face;

        this.user_authorized = data.user_authorized;

		    // fb connect
		    this.fb_api_key = data.fb_api_key;

        // helper methods
        this.year_start = new Date(this.year, 0, 1);
        this.today = new Date();
        this.day_start = new Date(this.year, this.today.getMonth(), this.today.getDate());

        // initialization code
        this.widget.find('.nav a').unbind('click');
        this.widget.find('.nav a').click(this.navClickHandler);

        this.currentPanel = '';
        this.counterObjects = false;
        this.thermometerObjects = false;
        this.groupObjects = false;
        this.facebookObjects = false;
        this.infoObjects = false;
        this.faceObjects = false;
        //this.widget.find('>div[id^=b-]').remove();

        var nav = this.widget.find('.nav');

        // delete all existing panels
        this.widget.find('div.body').remove();

        for(var i in this.panels) {
            nav_element = nav.find('#n-'+i);
            nav_element.after('<div id="b-' + i + '" class="body '+i+'"></div>');
            //nav.before('<div id="b-' + i + '" class="body '+i+'"></div>');
        }
        this.widget.find('div.body').hide();

        return this;
    }
}

$(window).load(function(){
    if (ie6)
        return;

    co2m_widget = new CO2monitorWidget($('#widget'));
    co2m_widget.loadFromServer(function(){
        co2m_widget.activatePanel($.cookie('co2m_widget_panel'));
    });

});

function reloadWidget() {
    co2m_widget.loadFromServer(function(){
        co2m_widget.activatePanel($.cookie('co2m_widget_panel'));
    });
}

function getDateString() {
    var d = new Date();

    return String(d.getDate()).leftPad(2, '0') + '.' +
        String(d.getMonth() + 1).leftPad(2, '0') + '.' +
        d.getFullYear() + ' ' +
        String(d.getHours()).leftPad(2, '0') + ':' +
        String(d.getMinutes()).leftPad(2, '0') + ':' +
        String(d.getSeconds()).leftPad(2, '0');
}

function setDigits(digits, value) {
    value *= 1000;

    var frac = Math.frac(value);
    var value = value - frac;
    var cprev = value % 10;

    for(var i=7; i>=0; --i) {
        var c = (value % Math.pow(10, 8 - i)) / Math.pow(10, 7 - i);
        var y;

        if (i == 7)
            y = 2 - (c + frac) * 22;
        else if (frac && cprev >= 9)
            y = 2 - (parseInt(c) + frac) * 22;
        else if (frac) {
            frac = 0;
            y = 2 - parseInt(c) * 22;
        } else
            y = 2 - parseInt(c) * 22;

        digits[i].css('backgroundPosition', '0px ' + y + 'px');

        cprev = c;
    }
}










// Browser detection
var BrowserDetect = {
    init: function () {
        this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
        this.version = this.searchVersion(navigator.userAgent)
            || this.searchVersion(navigator.appVersion)
            || "an unknown version";
        this.OS = this.searchString(this.dataOS) || "an unknown OS";
    },
    searchString: function (data) {
        for (var i=0;i<data.length;i++) {
            var dataString = data[i].string;
            var dataProp = data[i].prop;
            this.versionSearchString = data[i].versionSearch || data[i].identity;
            if (dataString) {
                if (dataString.indexOf(data[i].subString) != -1)
                    return data[i].identity;
            }
            else if (dataProp)
                return data[i].identity;
        }
    },
    searchVersion: function (dataString) {
        var index = dataString.indexOf(this.versionSearchString);
        if (index == -1) return;
        return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
    },
    dataBrowser: [
        {
            string: navigator.userAgent,
            subString: "Chrome",
            identity: "Chrome"
        },
        {   string: navigator.userAgent,
            subString: "OmniWeb",
            versionSearch: "OmniWeb/",
            identity: "OmniWeb"
        },
        {
            string: navigator.vendor,
            subString: "Apple",
            identity: "Safari",
            versionSearch: "Version"
        },
        {
            prop: window.opera,
            identity: "Opera"
        },
        {
            string: navigator.vendor,
            subString: "iCab",
            identity: "iCab"
        },
        {
            string: navigator.vendor,
            subString: "KDE",
            identity: "Konqueror"
        },
        {
            string: navigator.userAgent,
            subString: "Firefox",
            identity: "Firefox"
        },
        {
            string: navigator.vendor,
            subString: "Camino",
            identity: "Camino"
        },
        {       // for newer Netscapes (6+)
            string: navigator.userAgent,
            subString: "Netscape",
            identity: "Netscape"
        },
        {
            string: navigator.userAgent,
            subString: "MSIE",
            identity: "Explorer",
            versionSearch: "MSIE"
        },
        {
            string: navigator.userAgent,
            subString: "Gecko",
            identity: "Mozilla",
            versionSearch: "rv"
        },
        {       // for older Netscapes (4-)
            string: navigator.userAgent,
            subString: "Mozilla",
            identity: "Netscape",
            versionSearch: "Mozilla"
        }
    ],
    dataOS : [
        {
            string: navigator.platform,
            subString: "Win",
            identity: "Windows"
        },
        {
            string: navigator.platform,
            subString: "Mac",
            identity: "Mac"
        },
        {
               string: navigator.userAgent,
               subString: "iPhone",
               identity: "iPhone/iPod"
        },
        {
            string: navigator.platform,
            subString: "Linux",
            identity: "Linux"
        }
    ]

};
BrowserDetect.init();

