
/**
 * @class FlashMovie allows for an imbeded flash movie which is 
 *        the core element for Embedded charts
 */
isc.defineClass("OPINIATOR_FlashMovie", isc.Canvas);
OPINIATOR_FlashMovie.addProperties({
    /**
     *  Initializes the superclass then Gets and Verifies the player
     *  version
     */
    initWidget : function () 
        {
        // call superclass implementation
        this.Super("initWidget", arguments);
        this.FlashPlayerVersion = this._getFlashPlayerVersion();
        this._verifyFlashPlayerVersion();
        },

    draw : function ()
        {
        this.Super("draw", arguments);
        //  Requried for .NET and Form capapbilities
        if(!document.embeds[this.ID] && !window[this.ID])
            {
            window[this.ID] = document.getElementById(this.ID); 
            }
        },

    getInnerHTML: function ()
        {
        var html = "";
        var flashvars = this.getFlashVariables();
        var movie = this.getFlashMovie();
        var bgcolor = this.backgroundColor;
        var width = this.getWidth();
        var height = this.getHeight();
        var id = this.getID();

        if ( this.FlashPlayerVersion.isIE )
            {
            html = '<object' + 
                ' id="' + id + '"' +
                ' height=' + height +
                ' width=' + width +
                ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"' +
                'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">'+
                '<param value="opaque" name="wmode"/>' +
                '<param value="'+ bgcolor + '" name="bgcolor"/>' +
                '<param value="'+ flashvars + '" name="FlashVars"/>' +
                '<param value="' + movie + '" name="movie"/>' +
                '</object>';

            }
        else
            {
            html = '<embed' + 
                ' name="'+ id + '"' +
                ' height='+ height +
                ' width='+ width +
                ' wmode="opaque"' +
                ' quality="high"' +
                ' allowScriptAccess="always"' +
                ' bgcolor="' + bgcolor + '"' +
                ' flashvars="' + flashvars + '"' +
                ' src="' + movie + '"' +
                ' type="application/x-shockwave-flash"' +
                ' pluginspage="http://www.macromedia.com/go/getflashplayer"' +
                '/>';
            }

        return html;
        },

    getFlashVariables: function ()
        {
        return "";
        },

    getFlashMovie: function ()
        {
        return "";
        },

    _verifyFlashPlayerVersion: function ()
        {
        // First check for installed version of Flash Player - we need a minimum of 6
        if( this.FlashPlayerVersion.major < 6 )
            {
            var installationConfirm = window.confirm("You need Adobe Flash Player 6 (or above) to view the charts. It is a free and lightweight installation from Adobe.com.");
            return false;
            }

        //Added for .NET AJAX and <FORM> compatibility

        return true;		
        },

    _getFlashPlayerVersion: function()
        {
        flashVersion = new OPINIATOR__FlashVersion([0,0,0], false);

        if( navigator.plugins && navigator.mimeTypes.length )
            {
            var x = navigator.plugins["Shockwave Flash"];
            if(x && x.description) 
                {
                flashVersion = new OPINIATOR__FlashVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."), false); }
            }
        else if ( navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0 )
            { 
            //If Windows CE
            var axo = null;
            var counter = 3;
            while(axo === null) 
                {
                try 
                    {
                    counter++;
                    axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+ counter);
                    flashVersion = new OPINIATOR__FlashVersion([counter,0,0], true);
                    } 
                catch (e) 
                    {
                    axo = null;
                    }
                }
            } 
        else
            { 
            // Win IE (non mobile)
            // Do minor version lookup in IE, but avoid Flash Player 6 crashing issues
            try
                { axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); }
            catch(e)
                {
                try 
                    {
                    axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
                    this.FlashVersion = new OPINIATOR__FlashVersion([6,0,21], true);
                    axo.AllowScriptAccess = "always"; // error if player version < 6.0.47 (thanks to Michael Williams @ Adobe for this code)
                    } 
                catch(e) 
                    { 
                    if ( flashVersion.major == 6) 
                        { return flashVersion; }
                    }
                try 
                    { axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); } 
                catch(e) {}
                }
            if (axo !== null) 
                {
                flashVersion = new OPINIATOR__FlashVersion(axo.GetVariable("$version").split(" ")[1].split(","), true);
                }
            }
        return flashVersion;
        }

    });


/**
 * Helper class for Flash Movie
 * 
 * @author ktyra (3/14/2009)
 */
function OPINIATOR__FlashVersion(arrVersion, isIE)
    {
    this.major = arrVersion[0] !== null ? parseInt(arrVersion[0], 0) : 0;
    this.minor = arrVersion[1] !== null ? parseInt(arrVersion[1], 0) : 0;
    this.rev = arrVersion[2] !== null ? parseInt(arrVersion[2], 0) : 0;
    this.isIE = isIE;
    }


/**
 * @class Class for the standard Fusion Chart based upon Flash 
 *        Movie
 */
isc.defineClass("OPINIATOR_FusionChart", OPINIATOR_FlashMovie);
OPINIATOR_FusionChart.addProperties({
    /**
     * @property Contains the URL to the Fusion Chart (a .swf file)
     */
    chart: null,

    /**
     * @property An object containing all the attributes of the 
     *           chart not associated with the data, trendlines or
     *           categories. Each property in the object becomes and
     *           attribute of the graph.
     */
    attributes: null,

    /**
     * @property trendlines Contains the description of trendlines 
     * for 2D charts.  The trendline is an array of trendline 
     * objects where the 'trendline' object is a properties object 
     * of the same format as chart properties.  See properties 
     * property. 
     */
    trendlines: null,

    /**
     * @property vertTrendlines Contains the description of 
     * vertical trendlines for 3D charts.  The trendline is an array
     * of trendline objects where the trendline object is a 
     * properties object of the same format as chart properties. 
     * See properties property. 
     */
    vertTrendlines: null,

    /**
     * @property horizTrendlines Contains the description of 
     * horizontal trendlines for 3D charts.  The trendline is an 
     * array of trendline objects where the trendline object is a 
     * properties object of the same format as chart properties. See 
     * properties property. 
     */
    horizTrendlines: null,

   /**
     * @property categories  Represents the x-axis labels. The 
     * categores property should contain an object of 
     * {attributes, labels}. 
     *  
     * The 'attributes' property is an attributes property in the 
     * same fasion as the charts attribute properties and an 
     * provides attributes for all the labels contained in the 
     * 'labels' array. Labels is an array of attribute objects. 
     * Every object in the labels array represents one label on the 
     * x-axis and the properties in the object represent the 
     * attributes of that label 
     */
    categories: null,

    /**
     *  @property  An Array of Data elemnts associated to be
     *             displayed in the chart.  The format of the data
     *             element is chart specificto be displayed in the
     *             chart.  The format of the data element is chart
     *             specific.
     */
    series: null,


    /**
     *  @property  An Array of Data elemnts associated to be
     *             displayed in the chart.  The format of the data
     *             element is chart specificto be displayed in the
     *             chart.  The format of the data element is chart
     *             specific.
     */
    dataset: null,


    initWidget : function () 
        {
        this.Super("initWidget", arguments);
        this._chartcache = null;
        },

    /**
     *  @overload   Overrides the OPINIATOR_FlashMovie
     *              getFlashVariables with the variables for the
     *              Chart.
     */
    getFlashVariables: function ()
        {
        if ( this._chartcache === null )
            {
            this._chartcache = escape(this.getChartXML());
            }

        return '&chartWidth='+ this.getWidth() + 
               '&chartHeight=' + this.getHeight() + 
               '&dataXML=' + this._chartcache;
        },

    /**
     * Overrides the Flash Movie getFlashMovie to returns the chart 
     * movie.  Use the getChart method to get the chart.
     *
     * @overload
     */
    getFlashMovie: function ()
        {
        return this.getChart();
        },

    /**
     * Returns the Fusion Chart URL (a .swf) file
     */
    getChart: function ()
        {
        return this.chart;
        },

    /**
     * Sets the Fusion Chart URL. Causes a redraw
     */
    setChart: function ( chart )
        {
        this.chart = chart;
        this._chartcache = null;
        },

    /**
     * Gets the Chart's attributes property
     */
    getAttributes: function ()
        {
        return this.attributes;
        },

    /**
     * Sets the charts attributes property and redraws
     * @param properties Properties object. 
     */
    setAttributes: function ( attributes )
        {
        this.attributes = attributes;
        this._chartcache = null;
        },

    /**
     * Gets the trendline property
     */
    getTrendlines: function ()
        { return this.trendlines; },

    /**
     * Sets the trendline property. 
     *
     * @param trendlines trendline array
     */
    setTrendlines: function ( trendlines )
        {
        this.trendlines = trendlines;
        this._chartcache = null;
        },

    _chartTrendlines: function ()
        { return this._chartElements( "trendlines", null, "line", this.getTrendlines()); },

    /**
     * Gets the vertical trendline property
     */
    getVertTrendlines: function ()
        { return this.vertTrendlines; },

    /**
     * Sets the vertical trendline property. 
     *
     * @param trendlines trendline array
     */
    setVertTrendlines: function ( trendlines )
        {
        this.vertTrendlines = trendlines;
        this._chartcache = null;
        },

    _chartVertTrendlines: function ()
        { return this._chartElements( "vTrendLines", null, "line", this.getVertTrendlines()); },

    /**
     * Gets the horizontal trendline property
     */
    getHorizTrendlines: function ()
        { return this.horizTrendlines; },

    /**
     * Sets the horizontal trendline property. 
     *
     * @param trendlines trendline array
     */
    setHorizTrendlines: function ( trendlines )
        {
        this.horizTrendlines = trendlines;
        this._chartcache = null;
        },

    _chartHorizTrendlines: function ()
        { return this._chartElements( "hTrendLines", null, "line", this.getHorizTrendlines()); },

    /**
     * Gets the categories property
     */
    getCategories: function ()
        { return this.categories; },

    /**
     * Sets the categories object
     *
     * @param catagories categories object
     */
    setCategories: function ( categories )
        {
        this.categories = categories;
        this._chartcache = null;
        },


    _chartCategories: function ()
        {
        var categories = this.getCategories();
        if ( categories !== null )
            {
            return this._chartElements("categories", categories.attributes,
                                       "category", categories.labels);
            }
        return "";
        },

    /**
     * Gets the dataset property
     */
    getDataset: function ()
        { return this.dataset; },

    /**
     *  Sets the dataset property
     */
    setDataset: function ( dataset )
        {
        this.dataset = dataset;
        this.series = null;
        this._chartcache = null;
        },

    /**
     * Returns the series property.
     */
    getSeries: function ()
        { return this.series; },

    /**
     *  Sets the series property
     */
    setSeries: function ( series )
        {
        this.series = series;
        this.dataset = null;
        this._chartcache = null;
        },

    _chartData: function ()
        {
        var xml = "";

        //  An array of datset's which each dataset having potential properties
        var series = this.getSeries();
        var dataset = this.getDataset();
        if ( series !== null )
            {
            var length = series.length;
            for ( var i = 0; i < length; i++ )
                {
                xml += this._chartElements("dataset", 
                                           series[i].attributes,
                                           "set", 
                                           series[i].dataset);
                }
            }
        else if ( dataset !== null )
            {
            length = dataset.length;
            for ( i = 0; i < length; i++ )
                {
                xml += this._chartElement("set", dataset[i], false);
                }
            }

        return xml;
        },

    /**
     * Adds color to each data point in the dataset.  Will not work 
     * on a series only a dataset 
     * 
     * @param colors    The array of colors. 
     */
    colorizeDataset: function ( colors )
        {
        if ( this.dataset !== null )
            {
            for ( var i = 0; i < colors.getLengh(); i++ )
                {
                if ( i < this.dataset.getLength() )
                    { this.dataset[i].color = colors[i]; }
                }
            this._chartcache = null;
            }
        },

    refreshChart: function ()
        {
        this._chartcache = null;
        this.redraw();
        },

    /**
     * Generates the XML description of the chart
     */
    getChartXML: function ()
        {
        //  If nothing's changed don't do all this processing again
        if ( this._chartcache !== null  )
            { return _chartcache; }

        // Convert the Properties into XML
        var xml = this._chartElement("graph", this.attributes, true);

        xml  += this._chartTrendlines();
        xml  += this._chartVertTrendlines();
        xml  += this._chartHorizTrendlines();
        xml  += this._chartCategories();
        xml  += this._chartData();

        xml += this._endChartElement("graph");

        return xml;
        },

    /**
     *  Creats and Element with inner elements.  Inner elements will
     *  have the same element name but different attributes
     */
    _chartElements: function (name, attrs, inner_name, inner_attrs)
        {
        var xml = "";

        if ( inner_name !== null && inner_attrs !== null )
            {
            xml = this._chartElement(name, attrs, true);

            for ( var i = 0; i < inner_attrs.length; i++)
                {
                xml += this._chartElement(inner_name, inner_attrs[i], false);
                }
            xml += this._endChartElement(name);
            }

        return xml;
        },

    /**
     *  Creates an element with the attributes
     */
    _chartElement: function (name, attrs, hasInnerContent)
        {
        var xml = "";

        if ( name !== null  )
            {
            if ( (attrs !== null && !attrs.isEmpty) || hasInnerContent )
                {
                xml = '<'+name;
                for ( var attr in attrs)
                    {
                    xml += ' ' + attr + '="'+this._encodeValue(attrs[attr])+'"';
                    }

                xml += hasInnerContent ? '>' : '/>';
                }
            }

        return xml;
        },

    /**
     * Ends an element
     */
    _endChartElement: function ( name )
        {
        if ( name !== null )
            {
            return '</'+name+'>';
            }

        return "";
        },

    _chartElementValue: function (name, value)
        {
        var xml = "";
        if ( value !== null )
            { 
            xml = this._chartElement(name, null, true); 
            xml += value; 
            xml += this._endChartElement(name); 
            }
        return xml;
        },

    _encodeValue: function ( value )
        {
        if ( isA.Boolean(value) )
            {
            return ( value ) ? "1" : "0";
            }
        else if ( isA.String(value) && value.startsWith('#') )
            {
            return value.substring(1);
            }
        return value;
        }

    });

/**
 * @class Class for the standard Fusion Chart based upon Flash 
 *        Movie
 */
isc.defineClass("OPINIATOR_FusionWidget", OPINIATOR_FusionChart);
OPINIATOR_FusionWidget.addProperties({
    /**
     * @property colorRange Contains the description of colors 
     * for 2D Bullet charts.  The colorRange is an array of 
     * 'color' objects where the 'color' object is a properties 
     * object of the same format as chart properties. See properties
     * property. 
     */
    colorRange: null,

    /**
     * @property value Contains the value indicator for  
     * for 2D Bullet charts.  The value is current value of the 
     * bullet. 
     */
    value: null,


    /**
     * @property target Contains the target indicator for
     * 2D Bullet charts.  The target is current target of the 
     * bullet. 
     */
    target: null,

    initWidget : function () 
        { this.Super("initWidget", arguments); },

    /**
     * Gets the colorRange property
     */
    getColorRange: function ()
        { return this.colorRange; },

    /**
     * Sets the colorRange property. 
     *
     * @param colorRange color array
     */
    setColorRange: function ( colorRange )
        {
        this.colorRange = colorRange;
        this._chartcache = null;
        },

    _chartColorRange: function ()
        { return this._chartElements("colorRange", null, "color", this.getColorRange()); },

    /**
     * Gets the value property
     */
    getValue: function ()
        { return this.value; },

    /**
     * Sets the value property. 
     *
     * @param value A number
     */
    setValue: function ( value )
        {
        this.value = value;
        this._chartcache = null;
        },


    _chartValue: function ()
        { return this._chartElementValue("value", this.getValue()); },

    /**
     * Gets the value property
     */
    getTarget: function ()
        { return this.target; },

    /**
     * Sets the value property. 
     *
     * @param value A number
     */
    setTarget: function ( target )
        {
        this.target = target;
        this._chartcache = null;
        },

    _chartTarget: function ()
        { return this._chartElementValue("target", this.getTarget()); },

    /**
     * Generates the XML description of the chart
     */
    getChartXML: function ()
        {
        //  If nothing's changed don't do all this processing again
        if ( this._chartcache !== null  )
            { return _chartcache; }

        // Convert the Properties into XML
        var xml = this._chartElement("chart", this.attributes, true);

        xml  += this._chartColorRange();
        xml  += this._chartValue();
        xml  += this._chartTarget();

        xml  += this._chartTrendlines();
        xml  += this._chartVertTrendlines();
        xml  += this._chartHorizTrendlines();
        xml  += this._chartCategories();
        xml  += this._chartData();

        xml += this._endChartElement("chart");

        return xml;
        }

    });


