$.seoChart = 
{
    colors: ['red', 'Teal', 'blue', 'Fuchsia', 'orange', '', '', '', '', '', '', '', '', ''],
    scale: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
    points: null,
    logRatio: 0,
    timeRatio: 0,
    minTime: 0,
    offset: null,
    chart: null,
    height:0,
    width:0,
    tooltip:null,
    parent:null,
    ctx: null,
    
    create: function (chartQuery, time, data, labels, events)
    {
        this.chart  = $(chartQuery);
        this.time   = time;
        this.data   = data;
        this.labels = labels;
        this.events = events;
        
        var self = this;
        this.chart.mousemove (function(e){
          var info = self.isOver(e.pageX, e.pageY);
          if (info == null) self.hideTooltip();
          else self.showTooltip (info[0], info[1]);
        });

        /*
         * Init sizes and positions
         */
        this.height = this.chart.height() - 10;
        this.width  = this.chart.width()  - 10;
        this.offset = this.chart.offset();

        /*
         * Build logarythmic scale ratio
         */
        var maxScale  = this.scale[this.scale.length - 1];
        var logScale  = Math.log(maxScale);
        this.logRatio = this.height / logScale;
        /*
         * Build time scale
         */
        this.minTime  = time[0].getTime();
        
        if (this.time.length > 1)
        {
            var maxTime    = (this.time.length == 1) ? this.minTime : time[time.length - 1].getTime();
            var deltaDay   = (maxTime - this.minTime) / 86400000;
            this.timeRatio = (this.width - 5) / deltaDay;
        }
        else
            this.timeRatio = 1;

        /*
         * Build points positions
         */
        this.points = [];
        for (var i = 0; i < data.length; i++)
        {
            this.points[i] = [];

            for (var j = 0; j < time.length; j++)
            {
                var x = this.getXValue(time[j])
                var y = this.getYValue (data[i][j]);
                this.points[i][j] = {x:x,y:y};
            }
        }
        
        this.draw();

        return this;
    },
    draw: function ()
    {
        ctx = this.chart.get(0).getContext("2d");

        if (this.parent == null)
        {
            this.parent = document.createElement("div");
            this.parent.style.position = "relative";
            this.chart.after (this.parent);
            $(this.parent).append(this.chart);
        }
        
        ctx.clearRect (0,0, this.chart.width(), this.chart.height());
        ctx.save();

        ctx.translate (0, 5);

        /*
         * Draw backgrounds
         */
        ctx.lineWidth = '1';
        ctx.lineCap = 'square';
        ctx.fillStyle = '#f2f2f2';
        ctx.strokeStyle = '#ccc';

        var y1 = this.getYValue (this.scale[0]);
        var y2 = this.getYValue (this.scale[9]);
        ctx.fillRect (5, y1, this.width - 5, y2);

        for (var i = 0 ; i < this.scale.length; i++)
        {
            var y = this.getYValue (this.scale[i-1]);

            ctx.beginPath();
            ctx.moveTo (5, y + 0.5);
            ctx.lineTo (this.width, y + 0.5);
            ctx.stroke();
        }

        /*
         * Draw Axis and Units
         */
        ctx.lineWidth = '2';
        ctx.strokeStyle = 'black';
        
        ctx.beginPath();
        ctx.moveTo (5, 0);
        ctx.lineTo (5, this.height);
        ctx.lineTo (this.width, this.height);

        $('.seoChartPositionLabel').remove();

        for (i = 0; i < this.scale.length; i++)
        {
            y = this.getYValue (this.scale[i]);
            ctx.moveTo (2, y);
            ctx.lineTo (5, y);
            
            this.drawPositionLabel (y, this.scale[i]);
        }

        $('.seoChartTimeLabel').remove();


        var mod = (this.time.length > 50) ? 3  : 1;

        for (i = 0 ; i < this.time.length; i++)
        {
            var x = this.getXValue (this.time[i]);
            ctx.moveTo (x, this.height);
            ctx.lineTo (x, this.height + 3);

            if (i%mod == 0)
                this.drawTimeLabel (x, this.time[i], i%2==0);
        }

        ctx.stroke();
        
        ctx.lineWidth = '1';
        ctx.strokeStyle = '#333';
        ctx.shadowColor = '#666';
        ctx.shadowOffsetX=2;
        ctx.shadowOffsetY=3;
        ctx.shadowBlur=4;

        /*
         * Draw Events
         */
        for (i = 0; i < this.events.length; i++)
        {
            x = this.getXValue (this.events[i].date);

            ctx.beginPath();
            ctx.moveTo (x + 0.5, 0);
            ctx.lineTo (x + 0.5, this.height);
            ctx.stroke();

            this.drawEventLabel (x, this.events[i].label);
        }

        /*
         * Draw graphs
         */
        for (i = 0; i < this.points.length; i++)
        {
            var j = 0;

            while (((y = this.points[i][j].y) == null) && j < this.points[i].length - 1)
            {
                j++;
            }

            if (j >= this.points[i].length) continue;
            
            x = this.points[i][j].x;

            ctx.strokeStyle = this.colors[i];

            ctx.beginPath();
            ctx.moveTo(x, y);

            for (; j < this.points[i].length; j++)
            {
                x = this.points[i][j].x;
                y = this.points[i][j].y;

                if (y == null) continue;
                
                ctx.lineTo(x, y);
            }

            ctx.stroke();
        }

        /*
         * Draw circles
         */
        for (i = 0; i < this.points.length; i++)
        {
            j = 0;

            while (((y = this.points[i][j].y) == null) && j < this.points[i].length - 1)
            {
                j++;
            }

            if (j >= this.points[i].length) continue;

            x = this.points[i][j].x;

            ctx.fillStyle = this.colors[i];

            for (; j < this.points[i].length; j++)
            {
                x = this.points[i][j].x;
                y = this.points[i][j].y;

                if (y == null) continue;

                ctx.beginPath();
                ctx.arc(x,y,3,0,Math.PI*2,true);
                ctx.fill();
            }
        }

        ctx.restore();
    },
    getYValue: function (val)
    {
        if (val == null) return null;
        return Math.round (Math.log (val) * this.logRatio);
    },
    getXValue: function (val)
    {
        return Math.round (((val.getTime() - this.minTime) / 86400000)  * this.timeRatio) + 5;
    },
    isOver: function (mx, my)
    {
        mx -= this.chart.offset().left;
        my -= this.chart.offset().top + 5;

        for (var i = 0; i < this.points.length; i++)
        {
            for (var j = 0; j < this.points[i].length; j++)
            {
                var x = this.points[i][j].x;
                var y = this.points[i][j].y;

                if (mx > x - 8 && mx < x + 8 && my > y - 8 && my < y + 8)
                {
                    return [i,j];
                }
            }
        }

        return null;
    },
    showTooltip: function (i, j)
    {
        if (this.data[i][j] == null) return;

        var div = $('#seoChartTooltip');
        var el;

        if (div.length == 0)
        {
            el = document.createElement("div");
            el.id = "seoChartTooltip";
            
            with (el.style)
            {
                display = 'none';
                position = 'absolute';
            }

            el.iValue = null;
            el.jValue = null;
            
            document.body.appendChild (el);

            div = $(el);
            div.addClass ('ui-state-default ui-corner-all');
        }

        el = div.get(0);

        if (i == el.iValue && j == el.jValue) return;

        el.iValue = i;
        el.jValue = j;

        el.innerHTML = this.getTooltipContent(i, j);

        el.style.left = this.points[i][j].x + this.chart.offset().left + 'px';
        el.style.top  = this.points[i][j].y + this.chart.offset().top + 'px';        

        this.chart.get(0).style.cursor = 'crosshair'

        div.fadeIn ('fast');
    },
    hideTooltip: function ()
    {
        var div = $('#seoChartTooltip');
        
        if (div.length == 0) return;

        var el = div.get(0);

        el.iValue = null;
        el.jValue = null;

        this.chart.get(0).style.cursor = 'default';

        div.fadeOut ('fast');
    },
    getTooltipContent: function (i, j)
    {
        var str = '<b>Date : </b>';
        str    += this.getDateAsText (this.time[j]);
        str    += '<br/>';
        str    += '<b>Position : </b>';
        str    += this.data[i][j];
        
        return str;
    },
    drawPositionLabel: function (y, position)
    {
        var el  = document.createElement("div");
        var div = $(el);
        var x   = 0;

        
        //y -= this.chart.height() + 4;
        //x -= 52;

        //alert(y)

        div.append (position);

        div.addClass ("seoChartPositionLabel");
        
        div.css ('position', 'absolute');
        div.css ('top', y + 'px');
        div.css ('left', x + 'px');
        div.css ('font-family', 'Verdana,sans-serif');
        div.css ('font-size', '7pt');
        div.css ('width', '50px');
        div.css ('text-align', 'right');
        
        div.appendTo (this.parent);
    },
    drawTimeLabel: function (x, date, even)
    {
        var el     = document.createElement("div");
        var div    = $(el);
        var y      = this.chart.height() + 4;
        var small  = this.time.length > 15;
        
        
        
        if (even)  y += 10;
        if (small) x += 15;

        div.append (this.getDateAsText(date, small));

        div.addClass("seoChartTimeLabel");

        div.css ('position', 'absolute');
        div.css ('top', y + 'px');
        div.css ('left', x + 'px');
        div.css ('font-family', 'Verdana,sans-serif');
        div.css ('font-size', '7pt');

        div.appendTo (this.parent);
    },
    drawEventLabel: function (x, label)
    {
        var el  = document.createElement("div");
        var div = $(el);
        var y = -12;
        
        div.append (label);

        div.addClass ('ui-state-default ui-corner-right');

        div.css ('position', 'absolute');
        div.css ('left', x + 'px');
        div.css ('top', y + 'px');
        div.css ('font-family', 'Verdana,sans-serif');
        div.css ('font-size', '8pt');
        div.css ('padding', '1px 2px');
        div.css ('cursor', 'default');
        
        div.appendTo (this.parent);
    },
    getDateAsText: function (date, small)
    {
        var year  = date.getFullYear();
        var month = date.getMonth() + 1;
        var day   = date.getDate();
        var str   = '';

        if (day < 10) str += '0';
        str += day;
        str += '/';
        if (month < 10) str += '0';
        str += month

        if (!small)
        {
            str += '/';
            str += year;
        }
        
        return str;
    },
    exportTo: function (format){
        var imgData = ctx.toDataURL('image/'+format);
        window.open(imgData, "_blank");
    }
};
