/*!
 * MarketData v1.0
 * http://alertir.com/
 *
 * Copyright 2011, Alert Investor Relations AB
 *
 * Date: 2011-10-03
 */

var MarketData_Chart = function(MarketData_UI, onReadyCallback) {

    var self = this;
    var version = 0.1;

    /**
     *
     */
    this.ui = MarketData_UI;

    /**
     *
     */
    this.chart = {};

    /**
     * Component-specific configuration for AnyChart Stock
     */
    this.chartConfig = {
    	utils: {
    		contextMenu: {
    			about: false,
    			versionInfo: false,
    			exportAsPngImage: false,
    			exportAsJpgImage: false,
    			exportAsPdf: false,
    			exportAsInteractivePdf: false,
    			customItems: [
    				{
    					id: "customMenuItemAboutAlertIR",
    					addSeparator: true,
    					text: "About Alert Investor Relations AB...",
    					dest: "http://www.alertir.com/"
    				}
    			]
    		}
    	},
        data: {
            // initial dummy block - currently needed for initialization
            dataSets: [
                {
                    id: "dsDummy",
                    sourceMode: "InternalData",
                    csvData: ""
                }
            ],
            dataProviders: {
                generalDataProviders: [
                    {
                        id: "dpDummy",
                        dataSet: "dsDummy",
                        fields: [
                            {
                                type: "Value",
                                column: 1
                            }
                        ]
                    }
                ],
                scrollerDataProviders: []
            }
        },
        eventMarkers: {
            settings: {
                font: {
                    size: 10
                }
            }
        },
        settings: {
            charts: [
                {
                    id: "idMainChart",
                    enabled: true,
                    height: 250,
                    seriesList: [],
                    tooltipSettings: {
                        groupedTooltip: {
                            labels: {
                                format: "{%SeriesIcon} <b><font color=\"%Color\">{%SeriesName}</font></b> {%Value}{numDecimals:2} (<font color=\"%ChangeColor\">{%PercentValueChange}{plusSign:true,numDecimals:2}%</font>)"
                            }
                        }
                    },
                    valueAxes: {
                        primary: {
                            scale: {}
                        }
                    },
                    legend: {
                        // right-most part
                        dateTime: {
                            enabled: true,
                            //format: "{%Date.FirstVisible}{\"%yyyy-%MM-%dd %HH:%mm\"} - {%Date.LastVisible}{\"%yyyy-%MM-%dd %HH:%mm\"}",
                            intervalFormats: [
                                {
                                    unit: "Day",
                                    count: 1,
                                    format: "{%Date.FirstVisible}{\"%yyyy-%MM-%dd\"} - {%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                },{
                                    unit: "Week",
                                    count: 1,
                                    format: "{%Date.FirstVisible}{\"%yyyy-%MM-%dd\"} - {%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                },{
                                    unit: "Month",
                                    count: 1,
                                    format: "{%Date.FirstVisible}{\"%yyyy-%MM-%dd\"} - {%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                },{
                                    unit: "Quarter",
                                    count: 1,
                                    format: "{%Date.FirstVisible}{\"%yyyy-%MM-%dd\"} - {%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                },{
                                    unit: "Year",
                                    count: 1,
                                    format: "{%Date.FirstVisible}{\"%yyyy-%MM-%dd\"} - {%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                }
                            ]
                        },
                        // left-most part
                        title: {
                            focusSettings: {
                                mouseOver: {
                                    //format: "{%Date.Current}{\"%yyyy-%MM-%dd %HH:%mm\"}",
                                    intervalFormats: [
                                        {
                                            unit: "Day",
                                            count: 1,
                                            format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                                        },{
                                            unit: "Week",
                                            count: 1,
                                            format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                                        },{
                                            unit: "Month",
                                            count: 1,
                                            format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                                        },{
                                            unit: "Quarter",
                                            count: 1,
                                            format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                                        },{
                                            unit: "Year",
                                            count: 1,
                                            format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                                        }
                                    ]
                                },
                                mouseOut: {
                                    //format: "{%Date.LastVisible}{\"%yyyy-%MM-%dd %HH:%mm\"}",
                                    intervalFormats: [
                                        {
                                            unit: "Day",
                                            count: 1,
                                            format: "{%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                        },{
                                            unit: "Week",
                                            count: 1,
                                            format: "{%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                        },{
                                            unit: "Month",
                                            count: 1,
                                            format: "{%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                        },{
                                            unit: "Quarter",
                                            count: 1,
                                            format: "{%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                        },{
                                            unit: "Year",
                                            count: 1,
                                            format: "{%Date.LastVisible}{\"%yyyy-%MM-%dd\"}"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    technicalIndicators: []
                }
            ],
            scroller: {
                enabled: true,
                timeScale: {
                    maxTicksCount: 12
                },
                insideSelectedRange: {
                    seriesFill: {
                        enabled: false
                    }
                },
                outsideSelectedRange: {
                    seriesFill: {
                        enabled: false
                    },
                    backgroundFill: {
                        type: "Gradient",
                        gradient: {
                            type: "Linear",
                            angle: 90,
                            keys: [
                                {
                                    color: "#ffffff"
                                },{
                                    color: "#eeeeee"
                                }
                            ]
                        }
                    }
                }
            },
            dataGrouping: {
                enabled: true,
                //maxVisiblePoints: 0,
                intervals: [
                    {
                        unit: "Minute",
                        count: 1,
                        maxVisiblePoints: 1440
                    },{
                        unit: "Minute",
                        count: 5,
                        maxVisiblePoints: 1440
                    },{
                        unit: "Hour",
                        count: 1,
                        maxVisiblePoints: 720
                    },{
                        unit: "Day",
                        count: 1,
                        maxVisiblePoints: 1092
                    },{
                        unit: "Week",
                        count: 1,
                        maxVisiblePoints: 780
                    },{
                        unit: "Month",
                        count: 1,
                        maxVisiblePoints: 450
                    },{
                        unit: "Quarter",
                        count: 1,
                        maxVisiblePoints: 200
                    },{
                        unit: "Year",
                        count: 1,
                        maxVisiblePoints: 1000
                    }
                ]
            },
            displayLocale: {
                defaultDateTimeFormat: {
                    format: "%yyyy-%MM-%dd %HH:%mm"
                },
                dateTime: {
                    time: {
                        pmString: "",
                        shortPmString: "",
                        amString: "",
                        shortAmString: ""
                    },
                    firstDayOfWeek: "Monday",
                    weekRule: "FirstFourDayWeek"
                }
            },
            outsideMargin: {
                all: 0,
                bottom: 5
            },
            insideMargin: {
                all: 0,
                left: 2,
                right: 4
            },
            rangeSelector: {
                enabled: false
            },
            timeScale: {
                selectedRange: {
                    type: "Unit",
                    unit: "Year",
                    count: 1,
                    anchor: "LastDate"
                },
                majorIntervalFormats: {
                    years: "%yyyy",
                    months: "%MMM",
                    days: "%MMM-%dd",
                    hours: "%MMM-%dd %HH",
                    minutes: "%dd %HH:%mm",
                    seconds: "%HH:%mm:%ss",
                    milliseconds: "%HH:%mm:%ss.%fff"
                },
                minorIntervalFormats: {
                    months: "%MMM",
                    days: "%dd",
                    hours: "%HH",
                    minutes: "%HH:%mm",
                    seconds: "%HH:%mm:%ss",
                    milliseconds: "%fff"
                }
            },
            tooltipSettings: {
                enabled: true,
                useGlobalTooltip: true,
                tooltipMode: "Grouped",
                groupedTooltip: {
                    title: {
                        //format: "{%Date.Current}{\"%yyyy-%MM-%dd %HH:%mm\"}",
                        intervalFormats: [
                            {
                                unit: "Day",
                                count: 1,
                                format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                            },{
                                unit: "Week",
                                count: 1,
                                format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                            },{
                                unit: "Month",
                                count: 1,
                                format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                            },{
                                unit: "Quarter",
                                count: 1,
                                format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                            },{
                                unit: "Year",
                                count: 1,
                                format: "{%Date.Current}{\"%yyyy-%MM-%dd\"}"
                            }
                        ],
                        font: {}
                    },
                    labels: {
                        font: {}
                    }
                }
            }
        }
    };

    /**
     *
     */
    this.cache = {
        data: {},
        set: function(key, val) {
            this.data[key] = val;
        },
        get: function(key) {
            return this.data[key] || null;
        },
        del: function(key) {
            if (this.data[key]) {
                delete this.data[key];
            }
        }
    };

    /**
     *
     */
    this.primary;

    /**
     * add/show specified technical analysis if configured
     */
    this.addAnalysis = function(config) {
        this.displayTechnicalAnalysis(true, config);
        jQuery(this.ui.state).trigger("jobDone", {
            type: "addAnalysis",
            data: config
        });
    };

    /**
     * remove/hide specified technical analysis
     */
    this.removeAnalysis = function(config) {
        this.displayTechnicalAnalysis(false, config);
        jQuery(this.ui.state).trigger("jobDone", {
            type: "removeAnalysis",
            data: config
        });
    };

    /**
     *
     */
    this.setChartVisibility = function(chartId, state) {
        var chart;
        if ((chart = this.chart.getChartById(chartId)) !== null) {
            chart.enabled = state;
        }
        jQuery(this.ui.state).trigger("jobDone", {
            type: "setChartVisibility",
            data: state
        });
    };

    /**
     *
     */
    this.setSeriesType = function(chartId, type) {
        var chart;
        if ((chart = this.chart.getChartById(chartId)) !== null) {
            var seriesListType = this.getSeriesListTypeName(type);
            for (var i = 0; i < chart.seriesList.length; i++) {
                chart.seriesList[i].type = seriesListType;
            }
        }
        jQuery(this.ui.state).trigger("jobDone", {
            type: "setSeriesType",
            data: type
        });
    };

    /**
     *
     */
    this.setScaleType = function(chartId, type) {
        var chart;
        if ((chart = this.chart.getChartById(chartId)) !== null) {
            var axis = chart.valueAxes.primary;
            if (type == "percent") {
                axis.scale.mode = "PercentChanges";
            } else {
                axis.scale.mode = "Values";
            }
        }
        jQuery(this.ui.state).trigger("jobDone", {
            type: "setScaleType",
            data: type
        });
        jQuery(this.ui.state).trigger("scaleTypeChanged", type);
    };

    /**
     *
     */
    this.getPrimaryId = function() {
        return this.primary;
    };

    /**
     *
     */
    this.setDateRange = function(type, unit, count, anchor) {
        this.chart.selectRange(type, unit, count, anchor);
        jQuery(self.ui.state).trigger("onDateRangeChanged", type);
    };

    /**
     *
     */
    this.zoomTo = function(startDate, endDate) {
        this.chart.zoomTo(startDate, endDate);
    };

    /**
     *
     */
    this.applyConfigChanges = function() {
        this.chart.applyConfigChanges();
        jQuery(this.ui.state).trigger("onApplyConfigChanges", true);
    };

    /**
     *
     */
    this.applySettingsChanges = function() {
        this.chart.applySettingsChanges(true);
    };

    /**
     *
     */
    this.applyEventMarkersChanges = function() {
        this.chart.commitEventMarkersChanges();
    };

    /**
     *
     */
    this.setChartWaitingState = function(bool) {
        if (bool && bool === true) {
            this.chart.disableInteractivity();
            this.chart.showWaitingState();
        } else {
            this.chart.hideWaitingState();
            this.chart.enableInteractivity();
        }
    };

    /**
     *
     */
    this.download = function(type) {
        switch (type) {
            case "jpg":
                this.chart.exportAsJPG();
            break;
            case "png":
                this.chart.exportAsPNG();
            break;
            case "pdf":
                this.chart.exportAsPDF();
            break;
        }
    };

    /**
     *
     */
    this.comparisonExists = function(id) {
        if (this.chart.getSeriesById("idMainChart", id) !== null) {
            return true;
        } else {
            return false;
        }
    };

    /**
     *
     */
    this.getComparisons = function() {
        var chart = this.chart.getChartById("idMainChart");
        return chart.seriesList;
    };

    /**
     *
     */
    this.getSeriesListTypeName = function(type) {
        if (type == "bar") {
            return "Bar";
        } else {
            return "Line";
        }
    };

    /**
     *
     */
    this.getChartDataSetId = function(chartId, seriesId) {
        return "ds_"+chartId+"_"+seriesId;
    };

    /**
     *
     */
    this.getChartDataProviderId = function(chartId, seriesId) {
        return "dp_"+chartId+"_"+seriesId;
    };

    /**
     *
     */
    this.findById = function(arr, id) {
        for (var i = 0; i < arr.length; i++) {
            if (arr[i].id == id) {
                return i;
            }
        }
        return -1;
    };

    /**
     *
     */
    this.getNumSeries = function(chartId) {
        chartId = chartId || "idMainChart";
        var chart = this.chart.getChartById(chartId);
        return chart.seriesList.length;
    };

    /**
     *
     */
    this.getSeriesById = function(chartId, seriesId) {
        return this.chart.getSeriesById(chartId, seriesId);
    };

    /**
     *
     */
    this.getFirstDate = function() {
         return this.chart.getFirstDate();
    };

    /**
     *
     */
    this.getFirstVisibleDate = function() {
         return this.chart.getFirstVisibleDate();
    };

    /**
     *
     */
    this.getLastDate = function() {
         return this.chart.getLastDate();
    };

    /**
     *
     */
    this.getLastVisibleDate = function() {
         return this.chart.getLastVisibleDate();
    };

    /**
     *
     */
    this.setScrollerSource = function(chartId, seriesId, dateRange) {
        var dataSetId = this.getChartDataSetId(chartId, seriesId);
        var dataProviderId = this.getChartDataProviderId(chartId, seriesId);
        this.chart.objectModel.data.dataProviders.scrollerDataProviders = [{
            id: dataProviderId,
            dataSet: dataSetId,
            column: 1
        }];
        this.chart.objectModel.settings.scroller.dataProvider = dataProviderId;
/*
        if (dateRange && dateRange[0] && dateRange[1]) {
            this.chart.objectModel.settings.timeScale.selectedRange = {
                type: "Custom",
                startDate: dateRange[0],
                endDate: dateRange[1],
                anchor: "LastDate"
            };
        }
*/
    };

    /**
     * @param object
     *  o.id: String ID
     *  o.title: String Title
     *  o.color: String Color in hex, e.g. #ffffff
     *  o.intraday: Boolean [false]
     */
    this.setPrimary = function(o) {

        if (!o.id || o.id === null) {
            console.error("","MarketData_Chart.setPrimary: No id specified");
            return;
        }

        var self = this;
        var id = o.id;
        var title = o.title || id;
        var color = o.color || "#275BA8";
        var intraday = o.intraday || false;
        var options = {};

        if (intraday) {
            options.resolution = "5min";
        }

        this.ui.md.getHistory(id, function(result) {
            var history = result[id],
                csv = "Date,Close,Volume,Open,High,Low\n",
                ts;
            for (var i = 0; i < history.length; i++) {
                if ((ts = history[i].getValue("timestamp"))) {
                    csv += ts+
                        ","+history[i].getValue("close")+
                        ","+history[i].getValue("volume")+
                        ","+history[i].getValue("open")+
                        ","+history[i].getValue("high")+
                        ","+history[i].getValue("low")+
                        "\n";
                }
            }
            if (self.primary !== null) {
                self.removeSeries({
                    chartId: "idMainChart",
                    seriesId: self.primary
                });
            }
            self.primary = id;
            self.addSeries({
                 chartId: "idMainChart",
                 seriesId: id,
                 seriesListName: title,
                 seriesListType: self.getSeriesListTypeName(self.ui.state.current.seriesType),
                 csv: csv,
                 color: color,
                 fieldColumn: 1,
                 intraday: intraday
            });

            self.setScrollerSource("idMainChart", id);

            if (o.callback) {
                o.callback();
            }

        }, options);
    }; // setPrimary

    /**
     * @param object
     *  o.id: String ID
     *  o.title: String Title
     *  o.color: String Color in hex, e.g. #ffffff
     *  o.intraday: Boolean [false]
     */
    this.addComparison = function(o) {
        if (!o.id || o.id === null) {
            console.error("","MarketData_Chart.addComparison: No id specified");
            return;
        }
        var self = this;
        var id = o.id;
        var title = o.title || id;
        var color = o.color || "#379B29";
        var intraday = o.intraday || false;

        var options = {
            from: this.ui.md.fd(this.chart.getFirstDate())
        };
        if (intraday) {
            options.resolution = "5min";
        }
        this.ui.md.getHistory(id, function(result) {
            var chartId = "idMainChart",
                history = result[id],
                csv = "Date,Close,Volume,Open,High,Low\n",
                ts;
            for (var i = 0; i < history.length; i++) {
                if ((ts = history[i].getValue("timestamp"))) {
                    csv += ts+
                        ","+history[i].getValue("close")+
                        ","+history[i].getValue("volume")+
                        ","+history[i].getValue("open")+
                        ","+history[i].getValue("high")+
                        ","+history[i].getValue("low")+
                        "\n";
                }
            }
            self.removeSeries({
                chartId: "idMainChart",
                seriesId: id
            });
            self.addSeries({
                 chartId: "idMainChart",
                 seriesId: id,
                 seriesListName: title,
                 seriesListType: self.getSeriesListTypeName(self.ui.state.current.seriesType),
                 csv: csv,
                 color: color
            });

            jQuery(self.ui.state).trigger("jobDone", {
                type: "addComparison",
                data: id
            });

        }, options);
    }; // addComparison

    /**
     *
     */
    this.removeComparison = function(id) {
        var self = this;
        this.removeSeries({
            chartId: "idMainChart",
            seriesId: id,
            callback: function() {
                jQuery(self.ui.state).trigger("jobDone", {
                    type: "removeComparison",
                    data: id
                });
            }
        });
    };

    /**
     *
     */
    this.markerGroup = function(groupId, chartId, seriesId, customEventMarkerGroupSettings) {

        var events = [];

        this.eventMarkerGroupSettings = {
            font: {
                color: "#ffffff"
            },
            shape: {
                fill: {
                    type: "Solid",
                    color: "#c95232"
                }
            },
            tooltip: {
                enabled: true,
                width: 180,
                font: {
                    size: 11
                },
                format: "<textformat leading=\"3\"><b>{%Title}</b></textformat><br /><p align=\"right\">{%SourceDate}{\"%yyyy-%MM-%dd\"}</p>"
            }
        };

        if (customEventMarkerGroupSettings) {
            jQuery.extend(true, this.eventMarkerGroupSettings, customEventMarkerGroupSettings);
        }

        this.add = function(date, attr, token, index) {
            events.push({
                id: groupId+":"+index,
                localeBasedDate: date,
                format: token,
                attributes: attr
            });
        };

        this.reset = function(clearEvents, autoCommit) {
            self.chart.removeEventMarkerGroup(groupId);
            if (autoCommit) {
                self.chart.applyEventMarkersChanges();
            }
            if (clearEvents) {
                events = [];
            }
        };

        this.render = function(callback, autoCommit) {
            this.reset(false, autoCommit);
            self.chart.addEventMarkerGroup(chartId, seriesId, {
                id: groupId,
                chart: chartId,
                series: seriesId,
                locale: {
                    dateTime: {
                        offset: -(new Date().getTimezoneOffset()/60),
                        format: "%u"
                    }
                },
                settings: this.eventMarkerGroupSettings,
                events: events
            });
            self.cache.set("marker:"+groupId, true);
            if (autoCommit) {
                self.chart.applyEventMarkersChanges();
            }
            if (callback) {
                callback();
            }
        };

    }; // markerGroup

    /**
     * @param object
     * - type: string type, e.g. press, report, insiders
     * - lang: string language
     * - callback: callback function executed when done
     */
    this.addMarker = function(o) {
        var type = o.type;
        var callback = o.callback || null;
        var autoCommit = o.autoCommit || false;
        var lang = o.lang || "en";
        var primary = this.getPrimaryId();
        var id = o.marketdata.id || "alertir";
        var self = this;

        if (this.cache.get("marker:"+type) === true) {
            this.chart.showEventMarkerGroup(type);
            if (callback) {
                callback();
            }
            return;
        }

        switch (type) {
            case "reports":
            case "press":
                this.ui.md.getPressEvents(id, function(result) {
                    if (result[id]) {
                        var m = new self.markerGroup(type, "idMainChart", primary),
                            events = result[id],
                            ts,
                            markerAttr;
                        m.eventMarkerGroupSettings.shape.fill.color = o.markers.bgcolor;
                        for (var i = 0; i < events.length; i++) {
                            if ((ts = events[i].getValue("timestamp"))) {
                                markerAttr = {
                                    Title: events[i].getValue("headline")
                                };
                                m.add(ts, markerAttr, o.markers.token, i);
                            }
                        }
                        m.render(callback, autoCommit);
                    } else {
                        if (callback) {
                            callback();
                        }
                    }
                }, o.marketdata);
            break;
            case "insiders":
                this.ui.md.getInsiderEvents(id, function(result) {
                    if (result[id]) {
                        var customEventMarkerSettings = {
                            tooltip: {
                                format: "<textformat leading=\"3\"><b>{%Title}</b></textformat><br />"+
                                        "<p>{%Type}</p>"+
                                        "<p>{%Value} {%Unit}</p>"+
                                        "<p align=\"right\">{%SourceDate}{\"%yyyy-%MM-%dd\"}</p>"
                            }
                        };
                        var m = new self.markerGroup(type, "idMainChart", primary, customEventMarkerSettings),
                            events = result[id],
                            prefix,
                            ts,
                            markerAttr;
                        m.eventMarkerGroupSettings.shape.fill.color = o.markers.bgcolor;
                        for (var i = 0; i < events.length; i++) {
                            if ((ts = events[i].getValue("detail_transaction_date"))) {
                                markerAttr = {
                                    Title: events[i].getValue("person_name"),
                                    Type: events[i].getValue("detail_transaction_type"),
                                    Value: events[i].getValue("detail_number_value"),
                                    Unit: events[i].getValue("detail_number_unit", "&nbsp;")
                                };
                                if (markerAttr.Value == "0") {
                                    continue;
                                } else {
                                    markerAttr.Value = Number(markerAttr.Value);
                                }
                                //numDec = (markerAttr.Unit != "&nbsp;") ? 2 : 0;
                                prefix = (markerAttr.Value > 0) ? "+" : "";
                                markerAttr.Value = prefix+self.ui.md.nf(markerAttr.Value, 0, self.ui.getDefaultLang());
                                m.add(ts, markerAttr, o.markers.token);
                            }
                        }
                        m.render(callback, autoCommit);
                    } else {
                        if (callback) {
                            callback();
                        }
                    }

                }, o.marketdata);
            break;
        }
    }; // addMarker

    /**
     *
     */
    this.removeMarker = function(type) {
        this.chart.hideEventMarkerGroup(type);
        jQuery(this.ui.state).trigger("jobDone", {
            type: "removeMarker",
            data: type
        });
    };

    /**
     * @param object
     * - chartId: ID for an existing chart
     * - seriesId: New ID for the series to add
     * - seriesListName: The series name (used in legend)
     * - seriesListType: Line, Bar
     * - csv: Data
     */
    this.addSeries = function(o) {

        if (!o || (!o.chartId || !o.seriesId || !o.seriesListName || !o.seriesListType || !o.csv)) {
            return;
        }
        o.fieldColumn = o.fieldColumn || 1;

        var chartId = o.chartId;
        var dataSetId = this.getChartDataSetId(o.chartId, o.seriesId);
        var dataProviderId = this.getChartDataProviderId(o.chartId, o.seriesId);
        var seriesId = o.seriesId;
        var intraday = o.intraday || false;

        if (this.chart.getSeriesById(chartId, seriesId) !== null) {
            return;
        }

        var targetChart = this.chart.getChartById(chartId);

        /*
        * tweak default date(time) format depending on intraday/interday
        *
        * TODO: make dateTimeFormat and dateOnlyFormat configurable and i18n-able
        */
        var dateTimeFormat = "%yyyy-%MM-%dd %HH:%mm";
        var dateOnlyFormat = "%yyyy-%MM-%dd";
        /*
        * only do this when setting/switching primary
        */
        if (chartId == "idMainChart" && this.primary == seriesId) {
            /*
                legend: {
                    // right-most part
                    dateTime: {
                        enabled: true,
                        //format: "{%Date.FirstVisible}{\"%yyyy-%MM-%dd %HH:%mm\"} - {%Date.LastVisible}{\"%yyyy-%MM-%dd %HH:%mm\"}",
            */
            // first for main chart
            if (targetChart.legend) {
                if (targetChart.legend.title && targetChart.legend.title.focusSettings) {
                    var focusSettings = targetChart.legend.title.focusSettings;
                    if (intraday) {
                        focusSettings.mouseOver.format = "{%Date.Current}{\""+dateTimeFormat+"\"}";
                        focusSettings.mouseOut.format = "{%Date.LastVisible}{\""+dateTimeFormat+"\"}";
                    } else {
                        focusSettings.mouseOver.format = "{%Date.Current}{\""+dateOnlyFormat+"\"}";
                        focusSettings.mouseOut.format = "{%Date.LastVisible}{\""+dateOnlyFormat+"\"}";
                    }
                }
                if (targetChart.legend.dateTime) {
                    var tdt = targetChart.legend.dateTime;
                    if (tdt.enabled && tdt.enabled === true) {
                        if (intraday) {
                            targetChart.legend.dateTime.format = "{%Date.FirstVisible}{\""+dateTimeFormat+"\"} - {%Date.LastVisible}{\""+dateTimeFormat+"\"}";
                        } else {
                            targetChart.legend.dateTime.format = "{%Date.FirstVisible}{\""+dateOnlyFormat+"\"} - {%Date.LastVisible}{\""+dateOnlyFormat+"\"}";
                        }
                    }
                }
            }
            // then for (global) tooltip (only when global and grouped)
            if (this.chart.objectModel && this.chart.objectModel.settings && this.chart.objectModel.settings.tooltipSettings) {
                var tooltipSettings = this.chart.objectModel.settings.tooltipSettings;
                if (tooltipSettings.useGlobalTooltip === true && tooltipSettings.tooltipMode == "Grouped") {
                    if (intraday) {
                        tooltipSettings.groupedTooltip.title.format = "{%Date.Current}{\""+dateTimeFormat+"\"}";
                    } else {
                        tooltipSettings.groupedTooltip.title.format = "{%Date.Current}{\""+dateOnlyFormat+"\"}";
                    }
                }
            }
        }

        // add data set
        this.chart.objectModel.data.dataSets.push({
            id: dataSetId,
            sourceMode: "InternalData",
            csvData: o.csv,
            csvSettings: {
                ignoreFirstRow: true,
                rowsSeparator: "\n",
                columnsSeparator: ","
            },
            locale: {
                dateTime: {
                    offset: -(new Date().getTimezoneOffset()/60),
                    format: "%u"
                }
            }
        });

        /*
        * for correct aggregation when data is grouped
        */
        var approximationTypes = [
            "Dummy", // index 0
            "Close",
            "Sum",   // Volume
            "Open",
            "High",
            "Low"
        ];

        // add data provider for series
        this.chart.objectModel.data.dataProviders.generalDataProviders.push({
            id: dataProviderId,
            dataSet: dataSetId,
            fields: [
                { type: "Value",  column: o.fieldColumn, approximationType: approximationTypes[o.fieldColumn] },
                { type: "Close",  column: 1,             approximationType: approximationTypes[1] },
                { type: "Volume", column: 2,             approximationType: approximationTypes[2] },
                { type: "Open",   column: 3,             approximationType: approximationTypes[3] },
                { type: "High",   column: 4,             approximationType: approximationTypes[4] },
                { type: "Low",    column: 5,             approximationType: approximationTypes[5] }
            ]
        });

        // add series to a chart
        targetChart.seriesList.push({
            id: seriesId,
            type: o.seriesListType,
            name: o.seriesListName,
            color: o.color,
            dataProvider: dataProviderId
        });

        if (o.callback) {
            o.callback(this);
        }
    }; // addSeries

    /**
     * @param object
     * - o.chartId: ID for an existing chart
     * - o.seriesId: ID for the series
     * - o.callback:
     */
    this.removeSeries = function(o) {

        if (!o || (!o.chartId || !o.seriesId)) {
            return;
        }

        var chartId = o.chartId;
        var dataSetId = this.getChartDataSetId(o.chartId, o.seriesId);
        var dataProviderId = this.getChartDataProviderId(o.chartId, o.seriesId);
        var seriesId = o.seriesId;
        var series = this.chart.getSeriesById(chartId, seriesId);

        if (series === null) {
            return;
        }

        var targetChart = this.chart.getChartById(chartId);

        // If there is no such series - do nothing.
        var index = targetChart.seriesList.indexOf(series);
        if (index == -1) {
            return;
        }

        // Remove series if it exists
        targetChart.seriesList.splice(index, 1);

        // Remove data provider
        index = this.findById(this.chart.objectModel.data.dataProviders.generalDataProviders, dataProviderId);
        if (index != -1) {
            this.chart.objectModel.data.dataProviders.generalDataProviders.splice(index, 1);
        }

        // Remove data set
        index = this.findById(this.chart.objectModel.data.dataSets, dataSetId);
        if (index != -1) {
            this.chart.objectModel.data.dataSets.splice(index, 1);
        }

        if (o.callback) {
            o.callback();
        }

    }; // removeSeries

    /**
     * dak: prototype support for various technical analyses
     *
     * handles inline as well as separate charts, driven by
     * configuration settings for each type of analysis
     *
     * TODO: colors, styling and such things (from config)
     * TODO: remove/adjust logging
     */
    this.displayTechnicalAnalysis = function(status, config) {
        var chart = null, key = null, settings = null, i, ta_param_period;

        if (!config) {
            return false;
        }

        if (!config.id) {
            return false;
        }

        key = config.id;

        if (this.chart) {
            chart = this.chart;
            if (chart.objectModel && chart.objectModel.settings) {
                settings = chart.objectModel.settings;
            }
        }

        if (!chart) {
            return false;
        }
        if (!settings) {
            return false;
        }

        var indicator = null, indicatorChart = null, separate = false, separateId = null;

        if (config.separate && config.separate === true) {
            /*
            * analysis uses a separate chart
            */
            separate = true;
            separateId = "chart_"+key;
            /*
            * if separate chart has already been created, find it
            */
            for (i = 0; i < settings.charts.length; i++) {
                if (settings.charts[i].id == separateId) {
                    indicatorChart = settings.charts[i];
                    break;
                }
            }
            /*
            * if not found/created, create it
            */
            if (!indicatorChart) {
                indicatorChart = {
                    id: separateId,
                    enabled: true,
                    height: 160,
                    topPadding: 10,
                    bottomPadding: 10,
                    technicalIndicators: [],
                    xAxis: {
                        labels: {
                            enabled: false
                        }
                    },
                    legend: {
                        title: {
                            enabled: false
                        },
                        dateTime: {
                            enabled: false
                        }
                    }
                };
                settings.charts[settings.charts.length] = indicatorChart;
            }
        } else {
            /*
            * analysis uses primary chart
            */
            indicatorChart = settings.charts[0];
        }

        /*
        * if indicator has already been created, find it
        */
        if (indicatorChart.technicalIndicators.length > 0) {
            for (i = 0; i < indicatorChart.technicalIndicators.length; i++) {
                if (indicatorChart.technicalIndicators[i].id == key) {
                    indicator = indicatorChart.technicalIndicators[i];
                    break;
                }
            }
        }

        /*
        * status: true => enable, false => disable
        */
        if (status) {
            if (separate === true && indicatorChart.enabled === false) {
                indicatorChart.enabled = true;
            }
            if (indicator) {
                // already created - (re)enable it
                indicator.enabled = true;
            } else {
                // not yet created - create it
                var ta = null, separateChartTweak = null;
                var ta_index = indicatorChart.technicalIndicators.length;
                var taBase = {
                    enabled: true,
                    id: key,
                    dataProvider: settings.charts[0].seriesList[0].dataProvider
                };
                if (config.type == "sma") {
                    ta_param_period = config.params.period || 20;
                    ta = {
                        type: "SMA",
                        smaIndicator: {
                            period: ta_param_period,
                            series: {
                                name: "SMA("+ta_param_period+")"
                            }
                        }
                    };
                } else if (config.type == "ema") {
                    ta_param_period = config.params.period || 20;
                    ta = {
                        type: "EMA",
                        emaIndicator: {
                            period: ta_param_period,
                            series: {
                                name: "EMA("+ta_param_period+")"
                            }
                        }
                    };
                } else if (config.type == "volume") {
                    ta = {
                        type: "Volume",
                        volumeIndicator: {
                            series: {
                                type: "StepLineArea",
                                name: "Volume",
                                legendItem: {
                                    labels: {
                                        format: "{%SeriesIcon} <b><font color=\"%Color\">{%SeriesName}</font></b> {%Value}{numDecimals:0}"
                                    }
                                }
                            }
                        }
                    };
                    if (separate) {
                        /*
                        * tweaked settings for volume chart if/when separate
                        */
                        separateChartTweak = {
                            tooltipSettings: {
                                groupedTooltip: {
                                    labels: {
                                        format: "{%SeriesIcon} <b><font color=\"%Color\">{%SeriesName}</font></b> {%Value}{numDecimals:0}"
                                    }
                                }
                            },
                            valueAxes: {
                                primary: {
                                    labels: {
                                        //format: "{%Value}{scale:(1000)(1000)(1000)|( K)( M)( B),numDecimals:0}"
                                        format: "{%Value}{numDecimals:0}"
                                    },
                                    scale: {
                                        minimumOffset: 0
                                    }
                                }
                            }
                        };
                    }
                } else if (config.type == "rsi") {
                    ta_param_period = config.params.period || 14;
                    ta = {
                        type: "RSI",
                        rsiIndicator: {
                            period: ta_param_period,
                            series: {
                                name: "RSI("+ta_param_period+")"
                            }
                        }
                    };
                } else if (config.type == "mfi") {
                    ta_param_period = config.params.period || 14;
                    ta = {
                        type: "MFI",
                        mfiIndicator: {
                            period: ta_param_period,
                            series: {
                                name: "MFI("+ta_param_period+")"
                            }
                        }
                    };
                } else {
                    // ignore unsupported analysis type
                }
                if (ta !== null) {
                    if (separate && separateChartTweak !== null) {
                        jQuery.extend(true, indicatorChart, separateChartTweak);
                    }
                    var taFinal = jQuery.extend(true, {}, taBase, ta);
                    indicatorChart.technicalIndicators[ta_index] = taFinal;
                }
            }
        } else {
            if (indicator) {
                indicator.enabled = false;
            }
            if (separate === true && indicatorChart.enabled === true) {
                indicatorChart.enabled = false;
            }
        }
        return true;
    }; // displayTechnicalAnalysis

    /**
     * dak: initialize custom entries for the context menu
     */
    this.initCustomMenuItems = function(chart) {
     	if (!chart) {
     	    return;
     	}
     	var self = this;
     	chart.onContextMenuCustomItemClick = function(id) {
     		if (self.chartConfig.utils.contextMenu.customItems) {
				for (var i = 0; i < self.chartConfig.utils.contextMenu.customItems.length; i++) {
					if (id == self.chartConfig.utils.contextMenu.customItems[i].id) {
						if (self.chartConfig.utils.contextMenu.customItems[i].dest) {
							window.open(self.chartConfig.utils.contextMenu.customItems[i].dest);
						}
					}
				}
			}
     	};
    };

    /**
     * dak: dump current object model as json into element with id = dest
     */
    this.dumpModel = function(dest) {
        dest = dest || "areaDump";
        var chart = this.chart.chart;
        var loc = document.getElementById(dest);
        if (!chart || !chart.flashObject || !chart.objectModel) {
            return;
        }
        if (!loc) {
            return;
        }
        loc.value = chart.flashObject.traceObject(chart.objectModel);
    };

    /**
     * Apply config from this.ui.config.chart to this.chartConfig
     */
    this.applyUserConfig = function() {

        if (this.ui.config.chart.fonts.defaults) {
            jQuery.extend(true, this.chartConfig.settings, {
                tooltipSettings: {
                    groupedTooltip: {
                        title: {
                            font: this.ui.config.chart.fonts.defaults
                        },
                        labels: {
                            font: this.ui.config.chart.fonts.defaults
                        }
                    }
                },
                scroller: {
                    timeScale: {
                        labels: {
                            font: this.ui.config.chart.fonts.defaults
                        }
                    }
                },
                defaults: {
                    chart: {
                        xAxis: {
                            labels: {
                                majorLabels: {
                                    font: this.ui.config.chart.fonts.defaults
                                },
                                minorLabels: {
                                    font: this.ui.config.chart.fonts.defaults
                                }
                            }
                        },
                        legend: {
                            title: {
                                font: this.ui.config.chart.fonts.defaults
                            },
                            labels: {
                                font: this.ui.config.chart.fonts.defaults
                            },
                            dateTime: {
                                font: this.ui.config.chart.fonts.defaults
                            }
                        }
                    }
                }
            });
            jQuery.extend(true, this.chartConfig.eventMarkers.settings, {
                font: this.ui.config.chart.fonts.defaults
            });

        }

        if (this.ui.config.chart.fonts.tooltip) {
            jQuery.extend(true, this.chartConfig.settings.tooltipSettings.groupedTooltip, {
                title: {
                    font: this.ui.config.chart.fonts.tooltip
                }
            });
            jQuery.extend(true, this.chartConfig.settings.tooltipSettings.groupedTooltip, {
                labels: {
                    font: this.ui.config.chart.fonts.tooltip
                }
            });
        }

        if (this.ui.config.chart.fonts.markers) {
            jQuery.extend(true, this.chartConfig.eventMarkers.settings, {
                font: this.ui.config.chart.fonts.markers
            });
        }

        if (this.ui.config.chart.fonts.scroller) {
            jQuery.extend(true, this.chartConfig.settings, {
                scroller: {
                    timeScale: {
                        labels: {
                            font: this.ui.config.chart.fonts.scroller
                        }
                    }
                }
            });
        }

    };

    if ((match = document.location.href.match(/afw_id=(MDA:.+?)($|&)/)) && match[1]) {
        this.primary = match[1];
    } else {
        this.primary = this.ui.config.ui.instruments[0].items[0].id;
    }

    /**
     *
     */
    this.chartBaseUri = this.ui.config.chart.chartBaseUri || "/javascript/shared/anychartstock/swf";

    /*
     * Init
     */
    this.chart = new AnyChartStock(this.chartBaseUri+"/AnyChartStock.swf?v="+version,
                                   this.chartBaseUri+"/Preloader.swf?v="+version);
    this.applyUserConfig();
    this.chart.setConfig(this.chartConfig);
    this.chart.wMode = "transparent";
    this.chart.needConfig = true;
    this.chart.onChartDraw = function() {
        self.chart.onChartDraw = null;
        if (self.ui.initDateRangePicker) {
            self.ui.initDateRangePicker(self.chart);
        }
        if (self.initCustomMenuItems) {
        	self.initCustomMenuItems(self.chart);
        }
        if (onReadyCallback) {
            onReadyCallback();
        }
        self.config.ready();
    };
    this.chart.write("md-chart");

};

