/// <reference name="MicrosoftAjax.js"/>
/// <reference name="Telerik.Web.UI.Common.Core.js" assembly="Telerik.Web.UI"/>

Type.registerNamespace("Telerik.Web.UI")

Telerik.Web.UI.GridScrollTooltipExtender = function (element)
{
    Telerik.Web.UI.GridScrollTooltipExtender.initializeBase(this, [element]);

    this._grid = null;
    this._toolTip = null;

    this._gridMouseDownDelegate = null;
    this._gridScrollDelegate = null;
    this._hideTimeout = null;

    var events = ["beforeShow", "show"];
    this._initializeEvents(events);

    var publicProps = ["left", "right", "top", "bottom", "hideDelay"];
    this._initializePublicProperties(publicProps);
};

Telerik.Web.UI.GridScrollTooltipExtender.prototype = {
    initialize: function ()
    {
        this._grid = $find(this.get_element().id);
        if (!this._grid) throw new Error("No RadGrid instance specified.");

        this._gridScrollDelegate = Function.createDelegate(this, this._gridScroll);
        this._grid.add_scroll(this._gridScrollDelegate);

        this._gridMouseDownDelegate = Function.createDelegate(this, this._gridMouseDown);
        $addHandler(this._grid.get_element(), "mousedown", this._gridMouseDownDelegate);

        this._toolTip = document.createElement("div");
        this._toolTip.style.position = "absolute";
        this._toolTip.style.display = "none";
        this._grid.get_element().appendChild(this._toolTip);
    },

    dispose: function ()
    {
        this._grid.remove_scroll(this._gridScrollDelegate);
        this._gridScrollDelegate = null;
        this._gridMouseDownDelegate = null;
    },

    _initializeEvents: function (events)
    {
        if (events)
        {
            var thisObject = this;
            for (var i = 0, l = events.length; i < l; i++)
            {
                var name = events[i];

                this["add_" + name] = function (eventName)
                {
                    return function (eventHandler)
                    {
                        this.get_events().addHandler(eventName, eventHandler);
                    };
                } (name);

                this["remove_" + name] = function (eventName)
                {
                    return function (eventHandler)
                    {
                        this.get_events().removeHandler(eventName, eventHandler);
                    };
                } (name);

                this["raise_" + name] = function (eventName)
                {
                    return function (args)
                    {
                        var handler = this.get_events().getHandler(eventName);
                        if (handler)
                        {
                            if (!args)
                            {
                                args = new Sys.CancelEventArgs();
                            }
                            handler(this, args);
                        }
                    };
                } (name);
            }
        }
    },

    _buildEventArgs: function (eventArgs, eventData, writable)
    {
        for (var property in eventData)
        {
            var name = property;
            var value = eventData[property];

            if (name.indexOf("et_") > 0)
            {
                eventArgs[name] = value;
                continue;
            }

            eventArgs["_" + name] = value;

            eventArgs["get_" + name] = function (propertyName)
            {
                return function ()
                {
                    return this["_" + propertyName];
                }
            } (name);

            if (writable)
            {
                eventArgs["set_" + name] = function (propertyName)
                {
                    return function (value)
                    {
                        this["_" + propertyName] = value;
                    }
                } (name);
            }
        }

        return eventArgs;
    },

    _initializePublicProperties: function (properties)
    {
        for (var i = 0; i < properties.length; i++)
        {
            this["_" + properties[i]] = 0;

            this["get_" + properties[i]] = function (side)
            {
                return function ()
                {
                    return this["_" + side];
                };
            } (properties[i]);

            this["set_" + properties[i]] = function (side)
            {
                return function (value)
                {
                    this["_" + side] = value;
                }
            } (properties[i]);
        }
    },

    _gridMouseDown: function (e)
    {
        var target = e.target || e.srcElement;
        if (target && this._grid._gridDataDiv && target === this._grid._gridDataDiv)
        {
            this.showTooltip();
        }
    },

    showTooltip: function ()
    {
        this._grid.raise_scroll(new Telerik.Web.UI.GridScrollEventArgs(this._grid._gridDataDiv));
    },

    hideTooltip: function ()
    {
        this._toolTip.style.display = "none";
    },

    _gridScroll: function (grid, args)
    {
        var tableView = grid.get_masterTableView();
        var items = tableView.get_dataItems();

        var scrolledItemIndex = this._getScrolledItemIndex(args, items.length);
        var scrolledItem = items[scrolledItemIndex];
        var toolTipContent = this._getScrolledItemTooltip(scrolledItem);

        var eventData = {
            itemIndex: scrolledItemIndex,
            item: scrolledItem,
            toolTipContent: toolTipContent
        };
        var args = this._buildEventArgs(new Sys.CancelEventArgs(), eventData, false);

        this.raise_beforeShow(args);
        if (args.get_cancel())
        {
            return;
        }

        this._showItemTooltip(toolTipContent);

        this._resetHideTimeout();

        this.raise_show(args);
    },

    _getScrolledItemIndex: function (scrollArgs, itemCount)
    {
        var avgItemHeight = scrollArgs.get_scrollControl().scrollHeight / itemCount;
        var scrollTolerance = .2;
        return Math.floor(scrollArgs.get_scrollTop() / avgItemHeight + scrollTolerance);
    },

    _getScrolledItemTooltip: function (item)
    {
        var nestedViewItem = item.get_element().nextSibling;
        var toolTipElement = $telerik.getElementByClassName(nestedViewItem, "tooltip");

        return toolTipElement.parentNode.innerHTML;
    },

    _positionToolTip: function ()
    {
        var gridEl = this._grid.get_element();
        var loc = $telerik.getLocation(gridEl);
        var dim = $telerik.getSize(gridEl);
        var toolTipDim = $telerik.getSize(this._toolTip);
        var toolTipPos = { x: 0, y: 0 };

        if (this.get_right() > 0)
        {
            toolTipPos.x = loc.x + dim.width - toolTipDim.width - this.get_right();
        }
        else
        {
            toolTipPos.x = loc.x + this.get_left();
        }

        if (this.get_bottom() > 0)
        {
            toolTipPos.y = loc.y + dim.height - toolTipDim.height - this.get_bottom();
        }
        else
        {
            toolTipPos.y = loc.y + this.get_top();
        }

        $telerik.setLocation(this._toolTip, toolTipPos);
    },

    _showItemTooltip: function (toolTipContent)
    {
        this._toolTip.innerHTML = toolTipContent;
        this._showTooltip();

        this._positionToolTip();
    },

    _resetHideTimeout: function ()
    {
        if (this._hideTimeout)
        {
            clearTimeout(this._hideTimeout);
        }
        this._hideTimeout = setTimeout(Function.createDelegate(this, this.hideTooltip), this.get_hideDelay());
    },

    _showTooltip: function ()
    {
        this._toolTip.style.display = "";
    },

    get_grid: function ()
    {
        return this._grid;
    },
    set_grid: function (value)
    {
        this._grid = value;
    }
};

Telerik.Web.UI.GridScrollTooltipExtender.registerClass("Telerik.Web.UI.GridScrollTooltipExtender", Sys.UI.Behavior);