mp.report.events = {};
mp.report.events.views = {};
mp.report.events.click_handlers = function() {

    $("#export_link").click(function() {
        var build_url = function(params) {
            params.format = 'csv';
            if (mp.report.globals.api_sig) { params.api_sig = mp.report.globals.api_sig; }
            var arr = [];
            for (var key in params) {
                if (key && params[key]) {
                    if (params[key].constructor == Array) {
                        params[key] = $.toJSON(params[key]);
                    } 
                    arr.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
                }
            }
            
            var url = mp.globals.domain + '/api/2.0/' + params.service + '/';
            if (params.endpoint) { url += params.endpoint; }
            if (arr.length) { url += '?' + arr.join('&'); }
            return url;
        };
        mpmetrics.track('export csv');
        
        var r = mp.report.globals.nav.getURLRequest();
        var p = $.extend({}, mp.report.globals.params, r.params);
        p = mp.report.events.validate_params(p);
                    
        window.location = build_url(p);
    });

    $('.retention .percent').click(mp.report.events.show_retention_chart);
}; 

mp.report.events.show_retention_chart = function(series) {
    var row = $(this).closest('tr');
    var event_name = $('td:first-child', row).text();
    var series = $('.retention .percent', row).index(this);


    var unit = mp.report.globals.table_params.unit;
    var desc = (series+1) + ' ' + unit + ' retention rate by date for the "' + event_name + '" event';

    mpmetrics.track('retention chart viewed', {'unit': unit, 'series': (series+1).toString()});

    $('#retention-chart').html('<div class="loader"><img src="' + mp.globals.img_dir + '/ajax/ajax-loader-big.gif" /></div>');

    $.fn.colorbox({
        'href': '#retention-chart-wrapper',
        'innerWidth': 800,
        'innerHeight': 481,
        'inline': true,
        'onComplete': function() {
            $('#retention-chart-header').html(event_name + ' retention rate');
            $('#retention-chart-desc').html(desc);
            $('#retention-chart-wrapper').show();
            mp.report.events.create_retention_chart('retention-chart', event_name, series);
        },
        'onCleanup': function() {
            $('#retention-chart').html('');
            $('#retention-chart-wrapper').hide();
        }
    });
}

mp.report.events.create_retention_chart = function(element_id, event_name, series) {
    var unit = mp.report.globals.table_params.unit;
    var today = new Date();
    today = new Date(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
    var from_date = new Date(today);
    var to_date = new Date(today);
    var adjust = series + 1;
    switch (unit) {
        case 'day':
            from_date.addDays(-28-adjust);
            to_date.addDays(-adjust);
            break;
        case 'week':
            from_date.addWeeks(-12-adjust);
            to_date.addWeeks(-adjust);
            break;
        case 'month':
            from_date.addMonths(-12-adjust);
            to_date.addMonths(-adjust);
            break;
    }
    from_date = from_date.toString('yyyy-MM-dd');
    to_date = to_date.toString('yyyy-MM-dd');

    var chart = new RetentionChart();
    var params = {
        'service': 'events',
        'endpoint': 'retention',
        'unit': unit,
        'project_id': mp.report.globals.project_id,
        'from_date': from_date,
        'to_date': to_date,
        'event': [event_name]
    };
    params['series'] = series;
    chart.create(element_id, {title: null, subtitle: null}, params);
}

mp.report.events.start_realtime = function() {
    realtime.get_data({
        'api_sig': mp.report.globals.api_sig,
        'interval': 1,
        'limit': 255,
        'project_id': mp.report.globals.project_id,
        'unit': 'day',
        'type': mp.report.globals.table_params.type
    }, realtime.update);
};

mp.report.events.validate_params = function(p) {
    var params = {};
    
    p.endpoint = p.endpoint || p.type;
    
    switch(p.service) {
        case 'events':        
            if (p.endpoint == 'retention') {
                if (p.event.length == 1) {
                    params.chart_sub_type = p.chart_type;
                    params.chart_type = 'retention';   
                    params.limit = 7;
                    params.interval = 8;
                } else {
                    // going from retention -> multiple events via advanced
                    params.endpoint = null;
                    params.type = p.type || 'general';
                }
            }
            break;
                
        case 'events/properties':
            params.event = p.event[0];
            params.limit = 12;
            if (p.endpoint == 'retention') {
                params.endpoint = null;
                params.type = p.type || 'general';
            }
            break;
    }
    
    var analysis_types = ['unique', 'average', 'general'];
    for (var i in analysis_types) {
        if (analysis_types[i] == p.endpoint) {
            params.type = p.endpoint;
            params.endpoint = null;
            break;
        }
    }
    
    params = $.extend({}, p, params);
    return params;
};

mp.report.events.get_titles = function(p) {
    var title = '', 
        subtitle = '',
        ev = p.event,
        times = { day: 'day', week: 'week', month: 'month', hour: 'hour'},
		endpoint = p.endpoint || p.type;

        switch(p.service) {
        case 'events':        
            switch(endpoint) {
                case 'unique':
                    if (ev.length > 1) {
                        title = 'Unique visitors';
                        subtitle = 'Number of unique visitors who caused each event per ' + 
                            times[p.unit] + '.';
                    } else {
                        title = 'Unique visitors - ' + ev;
                        subtitle = 'Number of unique visitors who caused the ' + 
                            ev[0] + ' event per ' + times[p.unit] + '.';
                    }
                    break;
                case 'average':
                    if (ev.length > 1) {
                        title = 'Average visitors';
                        subtitle = 'Number of times per ' + times[p.unit] + 
                            ' an average visitor caused each event ';
                    } else {
                        title = 'Average visitors - ' + ev;
                        subtitle = 'Average number of times unique visitors caused the ' + 
                            ev[0] + ' event.';
                    }
                    break;
                case 'general':
                    if (ev.length > 1) {
                        title = 'Total visitors';
                        subtitle = 'Total number of times each event was recorded.';
                    } else {
                        title = 'Total visitors - ' + ev[0];
                        subtitle = 'Total number of times the ' + ev[0] + ' event was recorded.';
                    }
                    break;
                case 'retention':
                    title = 'Retention - ' + ev;
                    subtitle = 'Percent of visitors from each time period who came back and caused this event again.';
                    break;
            }
            break;
        case 'events/properties':
            switch(endpoint){
                case 'unique':
                    title = 'Unique visitors - ' + ev + ' -> ' + p.name;
                    subtitle = 'The number of unique visitors who triggered the event with this property.';
                    break;
                case 'general':
                    title = 'Total visitors - ' + ev + ' -> ' + p.name;
                    subtitle = 'The number of total visitors who triggered the event with this property.';
                    break;
                case 'average':
                    title = 'Average visitors - ' + ev + ' -> ' + p.name;
                    subtitle = 'Average number of times this event and property were caused per visitor.';
                    break;
                // case 'retention':
            }
            break;
            
        // case 'events/geo':
        //     params.event = ev[0];
        //     params.interval = 1;
        //     // Only limit bar, not map
        //     if (p.chart_type == 'bar' && !p.values) { params.limit = 20; }
        //     var timeframe = '';
        //     switch(p.unit) {
        //         case 'hour':
        //             timeframe = 'this hour';
        //             break;
        //         case 'day':
        //             timeframe = 'today';
        //             break;
        //         case 'week':
        //             timeframe = 'this week';
        //             break;
        //         case 'month':
        //             timeframe = 'this month';
        //     }
        //     switch(p.endpoint){
        //         case 'unique':
        //             title = 'Unique visitors - ' + ev;
        //             subtitle = 'The number of unique visitors from each country who caused this event ' + timeframe;
        //             break;
        //         case 'general':
        //             title = 'Total visitors - ' + ev;
        //             subtitle = 'Total number of times visitors from each country caused this event ' + timeframe;
        //             break;
        //         case 'average':
        //             title = 'Average visitors - ' + ev;
        //             subtitle = 'Average number of times unique visitors from each country caused this event ' + timeframe;
        //     }
        //     break;
    }
    
    return { 'title': title, 'subtitle': subtitle };
};

mp.report.events.views.main = function(params) { 
    $("#graph").html('<div class="loader"><img src="' + mp.globals.img_dir + '/ajax/ajax-loader-big.gif" /></div>');
    var titles = mp.report.events.get_titles(params);
    mp.report.events.graph(titles.title, titles.subtitle, params);
};

mp.report.events.graph = function(title, subtitle, params) {
    /* Handle charts */
    var chart = '', 
        chart_type = params.chart_type, 
        format = 'json';
    
    delete params.chart_type;
    
    switch(chart_type) {
        case 'pie': 
            if (params.endpoint == 'average') {
                chart = new AveragePieChart();
            } else {
                chart = new PieChart();
            }
            break;
        case 'line':
            chart = new Chart();
            break;
        case 'retention':
            if (params.chart_sub_type == 'table') {
                chart = new Table();
                delete params.chart_sub_type;
            } else {
                chart = new LineChart();
            }
            break;
        case 'map':
            chart = new Map();
            format = 'xml';
            break;
        case 'bar':
            chart = new Bar();
            break;
        default:
            chart = new Chart();
    }
    
    chart.create(
        'graph',
        {   // Meta
            title: title,
            subtitle: subtitle
        },
        params,
        format
    );
};


mp.report.events.views.advanced_events = function() {
    if (mp.report.globals.advanced_state != 'events') {
        mp.report.globals.advanced_state = 'events';
        mp.report.advanced.fill_advanced(mp.report.globals.wrappers.event.adv_map);
    }
};

mp.report.events.views.advanced_properties = function(event_name, property_name, params) {
    if (mp.report.globals.advanced_state != 'properties_' + event_name + '_' + property_name) {
        mp.report.globals.advanced_state = 'properties_' + event_name + '_' + property_name;
        
        var c = new Chart();

        var store_properties = function(data) {
            mp.report.globals.wrappers.property.values = {};
            for (var d in data) {
                if (data.hasOwnProperty(d)) {
                    mp.report.globals.wrappers.property.values[d] = data[d];
                }
            }
        };
        c.get_data(
            'values',
            {
                'project_id': mp.report.globals.project_id, 
                'event': event_name,
                'name': property_name,
                'unit': params.unit,
                'interval': params.interval,
                'limit': 255
            },
            function(data) {
                store_properties(data);
                mp.report.advanced.fill_advanced(mp.report.globals.wrappers.property.values);
            },
            'json',
            'events/properties'
        );
    }
};

// mp.report.events.views.advanced_maps = function(event_name) {
//     var c = new Chart();
//     delete mp.report.globals.params.values;
//     var store_properties = function(data) {
//         mp.report.globals.wrappers.maps.values = {};
//         for (var d in data) {
//             if (d) {
//                 mp.report.globals.wrappers.maps.values[d] = data[d];
//             }
//         }
//     };
//     c.get_data(
//         'countries',
//         {
//             'project_id': mp.report.globals.project_id, 
//             'event': event_name,
//             'unit': mp.report.globals.params.unit,
//             'interval': 1
//         },
//         function(data) {
//             store_properties(data.data);
//             mp.report.advanced.fill_advanced(mp.report.globals.wrappers.maps.values);
//         },
//         'json',
//         'events/geo'
//     );
// };

mp.report.events.views.prop_menu = function(events, selected_prop_name) {
    /* Build property menu on event click */
    if (events.length > 1) {
        $("#properties").hide();
        return;
    }
    var event_name = events[0];

    if (mp.report.globals.prop_menu_state != event_name) {
        mp.report.globals.prop_menu_state = event_name;
        
        // $("#properties").html('<div class="loader"><img src="' + mp.globals.img_dir + '/ajax/ajax-loader-big.gif" /></div>');
        $("#prop_load_img").show();
        $("#prop_table").html('').hide();
        $("#properties").show();
        
        var fill_menu = function(data) {
            var html = '', i = 0, num_props = 0, width = 0, arr = [];
            mp.report.globals.wrappers.property.map = {};
        
            var average_length = 0, chars_per_line = 100;
            // Count the number of properties
            for (var p in data) {
                if (p) {
                    num_props++;
                    average_length += (p).toString().length;
                }
            }
        
            average_length  = parseInt(average_length/num_props, 10);
        
            // Determine table width
            width = Math.ceil(chars_per_line/average_length);
            if (width > 7) {
                // max horizontal width
                width = 7;
            } 
        
            if (num_props < (width * 2)) {
                width = Math.ceil(num_props/2);
            }
        
            if (num_props == 2) {
                width = 2;
            }
        
            // Reset avg length in case width changes
            average_length = parseInt(chars_per_line / width, 10);
        
            // Build an array, with rows, cells equiv. to table
            var j = 0;
            for (var prop_name in data) {
                if (prop_name) {
                    if (i % width === 0 && i > 0) {
                        j++;
                    }
                    if (!arr[j]) { arr[j] = []; }
                    var val = hex_md5(prop_name);
                    mp.report.globals.wrappers.property.map[val] = prop_name;
                    arr[j].push([prop_name, val]);
                    i++;
                }
            }
        
            // Turn this array into a table
            html += '<table>';
            for (var row in arr) {
                if (row) {
                    html += '<tr>';
                    for (var cell in arr[row]) {
                        if (cell) {
                            var cleaned = mp.utility.sanitize(arr[row][cell][0]);
                            html += '<td val="' + arr[row][cell][1] + 
                                    '" class="prop_table_item" title="' + cleaned + '">' + 
                                    mp.utility.shorten_string(cleaned, average_length) + 
                                    '</td>';
                        }
                    }
                    html += '</tr>';
                }
            }
            html += '</table>';
        
            if (!html.length) {
                html = 'No properties found';
            }
            $("#prop_load_img").hide();
            $("#prop_table").html(html);
            $("#prop_table").show();
            if (selected_prop_name) {
                $("#prop_table .prop_table_item").removeClass("selected");
                $("#prop_table .prop_table_item[val='" + hex_md5(selected_prop_name) + "']").addClass("selected");
            }

            
        };
        
        var props = new Chart();
        props.get_data(
            "top",
            {
                'project_id': mp.report.globals.project_id, 
                'unit': "day",
                'interval': 7,
                'type': 'general',
                'event': event_name,
                'limit': 255
            },
            function(data) {
                fill_menu(data);
            },
            null,
            "events/properties"
        );
    } else if (selected_prop_name) {
        // Ensure that the correct property is highlighted
        $("#prop_table .prop_table_item").removeClass("selected");
        $("#prop_table .prop_table_item[val='" + hex_md5(selected_prop_name) + "']").addClass("selected");
    }

};

mp.report.events.views.table = function() {
    /* Handle events table updates */
    var numformat = function(num, places) {
        return mp.utility.commaize(mp.utility.floatformat(num, places));
    };
    
    var build_cell = function(amt, pct) {
        // Build the html for a table cell.  First cells have additional spans for realtime updates.
        var html = '<span class="amount">' + numformat(amt, 1) + '</span>';
        html += '<br />';
        html += '<span class="percent">';
        if (pct !== null) {
            if (pct < 0) {
                html += '<span class="red">';
            } else if (pct > 0) {
                html += '<span class="green">+';
            } else {
                html += '<span class="black">';
            }
            html += numformat(pct * 100, 1) + '%</span>';
        }
        html += '</span>'
        return html;
    };
    
    var format_weekly = function(data, interval) {
        var formatted = {};
        // First parse today
        var today = data.data.today.events;
        
        for (var i in today) {
            if (i) {
                var evt = today[i];
                formatted[evt.event] = [build_cell(evt.amount, evt.percent_change)];
            }
        }
        
        // Next parse the weekly data
        
        /*
        First thing we do is generate the dates we are looking for.  We 
        don't want to rely on the data returned to tell us what the dates are, 
        the data might be sparse.
        */
        today = new Date();
        var offset = today.getUTCOffset();
        offset = parseInt(offset, 10) / 100;
        today = today.addHours(offset * -1);
        var yesterday = today.add({days: -1});
        var series = [yesterday.toString("yyyy-MM-dd")];
        i = 0;
        while (i < interval) {
            var interval_day = yesterday.addWeeks(-1);
            series.push(interval_day.toString("yyyy-MM-dd"));
            i++;
        }
        // Now have today, yesterday, week before yesterday in our date list
        
        var values = data.data.weeks.values;
        for (var ev in mp.report.globals.wrappers.event.index) {
            if (ev) {
                if (formatted[ev] === undefined) { formatted[ev] = [build_cell(0, 0)]; }
                for (i in series) {
                    if (i) {
                        // Make sure event is actually there - if not, 0
                        var amt = ((values[ev] && values[ev][series[i]]) ? values[ev][series[i]] : 0);
                        formatted[ev].push(amt);
                    }
                }
            }
        }
        
        // Generate HTML to insert
        for (var event_name in formatted) {
            if (event_name) {
                var evnt = formatted[event_name];
                // Need to get the stored percentage info for the first cell -- 
                // it's already scaled, we don't want to do it again.
                var arr = [evnt[0]];
                for (var day = 1; day < evnt.length; day++) {
                    var current_amount = evnt[day], prev = evnt[day + 1], pct = null;
                    if (current_amount && prev) {
                        pct = (1 - current_amount/prev) * -1;
                    }
                    arr.push(build_cell(current_amount, pct));
                }
                formatted[event_name] = arr;
            }
        }
        
        // Parse series for sparkline
        var sparkline = data.data.sparkline, sparkline_data = {};
        for (var evt_name in formatted) {
            if (evt_name) {
                sparkline_data[evt_name] = [];
                var evt_info = sparkline.values[evt_name] || {};
                for (var date in sparkline.series) {
                    if (date) {
                        date = sparkline.series[date];
                        sparkline_data[evt_name].push((evt_info[date] || 0));
                    }
                }
            }
        }

        return { data: formatted, series: sparkline_data};
    };
    
    var format_retention = function(data, unit) {
        var formatted = {}, date_list = [], num_cells = 3;

        // Get today
        var today = new Date();
        var offset = today.getUTCOffset();
        offset = parseInt(offset, 10) / 100;
        today = today.addHours(offset * -1);
        
        // Create list of dates we are looking for
        switch(unit) {
            case 'day':
                var i = 0;
                while (i < num_cells) {
                    var day = today.addDays(-1);
                    date_list.push(day.toString("yyyy-MM-dd"));
                    i++;
                }
                break;
            case 'week':
                i = 0;
                var this_week = today.setWeek(today.getWeek());
                while (i < num_cells) {
                    var week = this_week.addWeeks(-1);
                    date_list.push(week.toString("yyyy-MM-dd"));
                    i++;
                }
                break;
            case 'month':
                i = 0;
                var this_month = today.addDays(-1 * today.getDate() + 1);
                while (i < num_cells) {
                    var month = this_month.addMonths(-1);
                    date_list.push(month.toString("yyyy-MM-dd"));
                    i++;
                }
                break;
        }

        date_list.sort();
        date_list.reverse();

        for (var e in mp.report.globals.wrappers.event.index) {
            if (e) {
                var info = data.data[e] || {};
                var val = info.values, j = 0;
                formatted[e] = [];
                if (val) {
                    while (j < date_list.length) {
                        var rates = val[date_list[j]];
                        var point_names = [], ptamt = 0;
                        for (var point in rates) {
                            if (point) {
                                point_names.push(point);
                            }
                        }
                        point_names.sort();
                        if (point_names.length > j) {
                            ptamt = rates[point_names[j]];
                        } 
                        
                        formatted[e].push(ptamt);
                        j++;
                    }
                } else {
                    while (j < date_list.length) {
                        formatted[e].push(0);
                        j++;
                    }
                }
            }
        }
        
        // Generate html
        for (var event_name in formatted) {
            if (event_name) {
                var evt_n = formatted[event_name];
                var arr = [];
                for (var day_string in evt_n) {
                    if (day_string) {
                        var evt_amt = evt_n[day_string] * 100;
                        var html = '<span class="percent">';
                        if (evt_amt < 20) {
                            html += '<span class="red">';
                        } else if (evt_amt > 50) {
                            html += '<span class="green">';
                        } else {
                            html += '<span class="blue">';
                        }
                        html += numformat(evt_amt, 1) + '%</span></span>';

                        arr.push(html);
                    }
                }
                formatted[event_name] = arr;
            }
        }
        return {data: formatted, label: unit};
    };

    var format = function(data, params) {
        var type = params.endpoint, unit = params.unit, interval = params.interval;
        if (type == 'table_update') {
            return format_weekly(data, interval);
        } else if (type == 'retention') {
            return format_retention(data, unit);
        }
        return {};
    };

    var insert = function(formatted, cell_class) {
        // Inserts into table cells.
        /* Expected format is
            { event_name: ["cell 1 html", "cell 2 html", etc ],
              event_name2: ["cell 1 html", etc]
            }
        */
        var series = formatted.series;
        var data = formatted.data;
        var label = formatted.label;
        $('#events_table .event_row').each(function() {
            var key = $(this).attr('id');
            var evt = mp.report.globals.wrappers.event.map[key];
            $("#events_table #" + key + " ." + cell_class).each(function(i) {
                $(this).html(data[evt][i]);
                if (cell_class == 'retention') {
                    $('.percent', this).click(mp.report.events.show_retention_chart);
                }
            });
            if (series && series[evt]) {
                $("#events_table #" + key + " .sparkline").sparkline(series[evt], mp.report.events.sparkline.default_settings);
            }
        });
        
        if (label) {
            $("#events_table .retention_label").text(label);
        }
        
    };

    var tb = new Chart(), tp = mp.report.globals.table_params;
    tb.get_data(
        tp.endpoint,
        {
            'project_id': mp.report.globals.project_id, 
            'unit': tp.unit,
            'interval': tp.interval,
            'event': tp.event,
            'type': tp.type
        },
        function(data) {
            insert(format(data, tp), tp.endpoint);
            mp.report.events.views.table.sort();
        },
        null,
        "events"
    );
};


mp.report.events.views.table.sort = function() {
    var table = $("#events_table");
    var table_body = $("tbody", table);
    var rows = table_body.children("tr").get();
    var th = $("th.sorted", table);
    var column = th.index();
    var extract_key = mp.report.events.views.table.sort.get_extract_key(th);
    $(rows).each(function(index, row) {
        row.sort_key = extract_key(row, column);
    });
    rows.sort(function(a, b) {
        if (a.sort_key < b.sort_key) {
            return -1;
        } else if (a.sort_key > b.sort_key) {
            return 1;
        } else {
            return 0;
        }
    });
    if (th.hasClass("descending")) {
        rows.reverse();
    }
    $(rows).each(function(index, row) {
        table_body.append(row);
    });
    var column_index_to_name = function(index) {
        var unit = mp.report.globals.table_params.unit;
        switch (index) {
            case 0: return 'name';
            case 1: return 'visitors today';
            case 2: return 'visitors yesterday';
            case 3: return 'visitors a week before yesterday';
            case 5: return 'retention one ' + unit + ' ago';
            case 6: return 'retention two ' + unit + 's ago';
            case 7: return 'retention three ' + unit + 's ago';
        }
    };
    mpmetrics.track('events table sorted', {
        'column': column_index_to_name(column),
        'direction': th.hasClass('descending') ? 'descending' : 'ascending'
    });
};


mp.report.events.views.table.sort.extract_alpha = function(row, column) {
    return $(row).children().eq(column).text().toLowerCase();
};
mp.report.events.views.table.sort.extract_amount = function(row, column) {
    return parseFloat($(row).children().eq(column).find("span.amount").text().replace(",", ""));
};
mp.report.events.views.table.sort.extract_percent = function(row, column) {
    return parseFloat($(row).children().eq(column).find("span.percent").text().replace("%", ""));
};
mp.report.events.views.table.sort.get_extract_key = function(th) {
    if ($(th).hasClass("sort_text")) {
        return mp.report.events.views.table.sort.extract_alpha;
    } else if ($(th).hasClass("sort_amount")) {
        return mp.report.events.views.table.sort.extract_amount;
    } else if ($(th).hasClass("sort_percent")) {
        return mp.report.events.views.table.sort.extract_percent;
    }
    return null;
};


mp.report.events.views.table.sort.init = function() {
    var table = $("#events_table");
    $("th", table).each(function(column) {
        if (mp.report.events.views.table.sort.get_extract_key(this) !== null) {
            $(this).addClass("clickable").click(function() {
                if ($(this).hasClass("sorted")) {
                    $(this).toggleClass("ascending descending");
                } else {
                    // reset previous sort column's default sort order
                    var prev = $("th.sorted").removeClass("sorted ascending descending");
                    if (prev.hasClass("default_ascending")) {
                        prev.addClass("ascending");
                    } else {
                        prev.addClass("descending");
                    }
                    $(this).addClass("sorted");
                }
                mp.report.events.views.table.sort();
            });
        }
    });
};


mp.report.events.sparkline = {};
mp.report.events.sparkline.default_settings = {   
    'fillColor': '#EBEBEB', 
    'lineColor': '#4E74A1', 
    'spotColor': '#4E74A1', 
    'minSpotColor': '#BD474B', 
    'maxSpotColor': '#4BBD47', 
    'spotRadius': 2, 
    'lineWidth': 1.4
};

