/**
 * dashboard-analytics.js
 *
 * @author Daniele De Nobili
 */

/*jslint nomen: true, plusplus: true, passfail: true, browser: true, devel: true */
/*global $, gapi, Pongho */

(function () {
    "use strict";

    $.debounce = function (fn, wait) {
        var timer;

        wait = wait || 250;

        return function () {
            var context = this, args = arguments;

            clearTimeout(timer);
            timer = setTimeout(function () {
                fn.apply(context, args);
            }, wait);
        };
    };
}());

(function () {
    "use strict";

    // Don't copy this!
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
    // http://stackoverflow.com/questions/588004/is-floating-point-math-broken
    function round(value) {
        return Math.round(value * 100) / 100;
    }

    // http://stackoverflow.com/a/3177985
    function formatNumber(value) {
        value = round(value);

        if (value < 1000) {
            return value;
        }

        return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.');
    }

    function formatFloat(value) {
        return round(value).toString().replace('.', ',');
    }

    function formatPercent(value) {
        return formatFloat(value) + '%';
    }

    function formatPeriod(value) {
        var sec_num = parseInt(value, 10),
            hours = Math.floor(sec_num / 3600),
            minutes = Math.floor((sec_num % 3600) / 60),
            seconds = sec_num - (hours * 3600) - (minutes * 60);

        hours = hours < 10 ? '0' + hours : hours;
        minutes = minutes < 10 ? '0' + minutes : minutes;
        seconds = seconds < 10 ? '0' + seconds : seconds;

        return hours + ':' + minutes + ':' + seconds;
    }

    gapi.analytics.ready(function () {

        var
            dateSelector,
            visitsContainer,
            visitsChart,
            reportConfig,
            reportMetrics = [],
            report,
            locationsContainer,
            locationsChart,
            keywordsContainer,
            keywordsReport,
            pageViewsContainer,
            pageViewsReport;

        // auth
        gapi.analytics.auth.authorize({
            'serverAuth': {
                'access_token': window.Pongho.analytics.accessToken
            }
        });


        // date selector
        dateSelector = new gapi.analytics.ext.DateRangeSelector({
            container: 'date-range-container',
            'start-date': Pongho.analytics.start,
            'end-date': Pongho.analytics.end
        });

        dateSelector.on('change', function (data) {
            visitsChart.set({query: data}).execute();
            report.set({query: data}).execute();

            locationsChart.set({query: data}).execute();

            keywordsContainer.addClass('loading').html('');
            keywordsReport.set({query: data}).execute();

            pageViewsContainer.addClass('loading').html('');
            pageViewsReport.set({query: data}).execute();
        });

        dateSelector.execute();


        // visits
        visitsContainer = $('#ga-visits-container');

        visitsChart = new gapi.analytics.googleCharts.DataChart({
            query: {
                ids: window.Pongho.analytics.id,
                'start-date': window.Pongho.analytics.start,
                'end-date': window.Pongho.analytics.end,
                metrics: 'ga:sessions',
                dimensions: 'ga:date'
            },
            chart: {
                container: visitsContainer.find('.chart').get(0),
                type: 'LINE',
                options: {
                    width: '100%'
                }
            }
        });

        visitsChart.execute();


        // reports
        reportConfig = {
            'ga:sessions': {
                label: 'Sessioni',
                format: formatNumber
            },
            'ga:users': {
                label: 'Utenti',
                format: formatNumber
            },
            'ga:pageviews': {
                label: 'Visualizzazioni di pagina',
                format: formatNumber
            },
            'ga:pageviewsPerSession': {
                label: 'Pagine/sessione',
                format: formatFloat
            },
            'ga:avgSessionDuration': {
                label: 'Durata sessione media',
                format: formatPeriod
            },
            'ga:bounceRate': {
                label: 'Frequenza di rimbalzo',
                format: formatPercent
            },
            'ga:percentNewSessions': {
                label: '% nuove sessioni',
                format: formatPercent
            }
        };

        $.each(reportConfig, function (index) {
            reportMetrics.push(index);
        });

        report = new gapi.analytics.report.Data({
            query: {
                ids: window.Pongho.analytics.id,
                'start-date': window.Pongho.analytics.start,
                'end-date': window.Pongho.analytics.end,
                metrics: reportMetrics.join(',')
            }
        });

        report.on('success', function (response) {
            var reportCode = '';

            $.map(response.columnHeaders, function (col, index) {
                var label = reportConfig[col.name].label,
                    value = reportConfig[col.name].format(response.rows[0][index]);

                reportCode += '<div class="reports__data"><span class="reports__label">' + label + '</span><span class="reports__value">' + value + '</span></div>';
            });

            visitsContainer.find('.reports').html(reportCode);
        });

        report.execute();


        // locations
        locationsContainer = $('#ga-locations-container');

        locationsChart = new gapi.analytics.googleCharts.DataChart({
            query: {
                ids: window.Pongho.analytics.id,
                'start-date': window.Pongho.analytics.start,
                'end-date': window.Pongho.analytics.end,
                metrics: 'ga:sessions',
                dimensions: 'ga:country',
                'max-results': 10,
                sort: '-ga:sessions'
            },
            chart: {
                container: locationsContainer.get(0),
                type: 'PIE',
                options: {
                    width: '100%',
                    pieHole: 4 / 9
                }
            }
        });

        locationsChart.execute();


        // keywords
        keywordsContainer = $('#ga-keywords-container');

        keywordsReport = new gapi.analytics.report.Data({
            query: {
                ids: window.Pongho.analytics.id,
                'start-date': window.Pongho.analytics.start,
                'end-date': window.Pongho.analytics.end,
                metrics: 'ga:pageviews',
                dimensions: 'ga:keyword',
                'max-results': 11,
                sort: '-ga:pageviews'
            }
        });

        keywordsReport.on('success', function (response) {
            var table = '<tr><th>' + Pongho.trans.Keyword + '</th><th>' + Pongho.trans.Visits + '</th>';

            $.map(response.rows, function (row) {
                var keyword = row[0], hits = row[1];

                if (keyword !== '(not set)') {
                    table += '<tr><td>' + keyword + '</td><td>' + hits + '</td></tr>';
                }
            });

            keywordsContainer.removeClass('loading').html('<table>' + table + '</table>');
        });

        keywordsReport.execute();


        // page views
        pageViewsContainer = $('#ga-page-views-container');
        pageViewsReport = new gapi.analytics.report.Data({
            query: {
                ids: window.Pongho.analytics.id,
                'start-date': window.Pongho.analytics.start,
                'end-date': window.Pongho.analytics.end,
                metrics: 'ga:pageviews',
                dimensions: 'ga:pageTitle,ga:pagePath',
                'max-results': 10,
                sort: '-ga:pageviews'
            }
        });

        pageViewsReport.on('success', function (response) {
            var table = '<tr><th>' + Pongho.trans.Page + '</th><th>' + Pongho.trans.Visits + '</th>';

            $.map(response.rows, function (row) {
                var title = row[0], url = window.Pongho.baseUrl + row[1], visits = row[2];

                table += '<tr><td><a href="' + url + '" target="_blank">' + title + '</a></td><td>' + visits + '</td></tr>';
            });

            pageViewsContainer.removeClass('loading').html('<table>' + table + '</table>');
        });

        pageViewsReport.execute();


        // responsive chart!
        $(window).resize($.debounce(function () {
            // fixme: il metodo execute() non ricrea il grafico, ma riesegue anche la query
            visitsChart.execute();
            locationsChart.execute();
        }));
    });
}());
