 import mx.resources.ResourceManager;
 import mx.resources.IResourceManager;
 import spark.components.DataGrid;
-import spark.components.Grid;  
+import spark.components.Grid;
 import spark.components.supportClasses.GridSelectionMode;
 import spark.components.supportClasses.CellPosition;
 import spark.events.GridEvent;
 import spark.events.GridCaretEvent;
 import spark.events.GridSelectionEvent;
+import spark.events.GridSelectionEventKind;
 import spark.skins.spark.DefaultGridItemRenderer;
 
 use namespace mx_internal;

/**
 *  DataGridAccImpl is a subclass of AccessibilityImplementation
 *  which implements accessibility for the DataGrid class.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5


internal class ItemAccInfo
{
    import mx.core.UIComponent;
    import spark.components.DataGrid;
    import spark.components.Grid;
    import spark.components.supportClasses.GridSelectionMode;
    import spark.components.supportClasses.CellPosition;
    import flash.geom.Rectangle;
    import flash.geom.Point;

    /**
     *  Constructor.
     */
    public function ItemAccInfo()
    {
        super();
    }

    /**
     *
     *  @param master The UIComponent instance that this AccImpl instance
     *  is making accessible.
     *  @param childID The childID of the item of interest.
     */
    public function setup(master:UIComponent, childID:uint):void
    {
        this.master = master;
        this.childID = childID;
        dataGrid = DataGrid(master);
        visibleRowIndices = null;
        visibleColumnIndices = null;
        if (dataGrid.columns)
        {
            columnCount = dataGrid.columns.length;
            visibleColumnCount = visibleColumnIndices == null ?
                columnCount : visibleColumnIndices.length;
        }
        else
        {
            columnCount = 0;
            visibleColumnCount = 0;
        }
        if (dataGrid.dataProvider)
        {
          rowCount = dataGrid.dataProvider.length;
            visibleRowCount = visibleRowIndices == null ?
                rowCount : visibleRowIndices.length;
        }
        else
        {
            rowCount = 0;
            visibleRowCount = 0;
        }
        headerCount = 0;
        visibleHeaderCount = 0;
        maxChildID = 0;
        isCellMode = false;
        isMultiSelect = false;
        isInvalid = false;
        isColumnHeader = false;
        rowIndex = 0;
        columnIndex = 0;
        visibleRowIndex = 0;
        visibleColumnIndex = 0;

        var itemIndex:int = childID - 1;
        if (dataGrid.columnHeaderBar && dataGrid.columnHeaderBar.visible)
        {
            // There are visible column headers, so their childIDs come first.
            itemIndex -= visibleColumnCount;
            headerCount = columnCount;
            visibleHeaderCount = visibleColumnCount;
        }
        else
        {
            // No header bar or it's invisible,
            // so we should not try to expose any data within it.
            headerCount = 0;
            visibleHeaderCount = 0;
        }
        var mode:String = dataGrid.selectionMode;
        isCellMode = (
            mode == GridSelectionMode.SINGLE_CELL
            || mode == GridSelectionMode.MULTIPLE_CELLS
        );
        isMultiSelect = (
            mode == GridSelectionMode.MULTIPLE_CELLS
            || mode == GridSelectionMode.MULTIPLE_ROWS
        );
        maxChildID = 0;
        // Account for visible headers.
        maxChildID += visibleHeaderCount;
        // Then for visible cells or rows as appropriate.
        if (isCellMode)
            maxChildID += visibleRowCount * visibleColumnCount;
        else
            maxChildID += visibleRowCount;
        isColumnHeader = false;
        isInvalid = false;
        if (childIDOutOfBounds(childID))
        {
            isInvalid = true;
            visibleColumnIndex = -1;
            visibleRowIndex = -1;
            itemIndex = -1;
        }
        else if (itemIndex < 0)
        {
            // This childID refers to a header, not a data row or cell.
            isColumnHeader = true;
            visibleColumnIndex = itemIndex + visibleColumnCount;
            visibleRowIndex = -1;
            itemIndex = -1;
        }
        else if (isCellMode)
        {
            visibleRowIndex = Math.floor(itemIndex / visibleColumnCount);
            visibleColumnIndex = itemIndex % visibleColumnCount;
        }
        else
        {
            visibleRowIndex = itemIndex;
            // Using 0 here so, for example, getItemRendererAt() calls still work for a row.
            visibleColumnIndex = 0;
        }
        rowIndex = visibleRowIndex;
        columnIndex = visibleColumnIndex;
        if (visibleRowIndex >= 0 && visibleRowIndices != null)
            rowIndex = visibleRowIndices[visibleRowIndex];
        if (visibleColumnIndex >= 0 && visibleColumnIndices != null)
            columnIndex = visibleColumnIndices[visibleColumnIndex];
    }

    // The master component reference for which this AccImpl is instantiated.
    public var master:UIComponent;
    // The childID within that component for which this accInfo is calculated.
    public var childID:uint;
    // The DataGrid reference for this instance.
    public var dataGrid:DataGrid;
    // Number of columns, headers, and rows overall.
    public var columnCount:int;
    public var headerCount:int;
    public var rowCount:int;
    // Number of columns, headers, and rows that are visible.
    // ("Visible" means not marked invisible by programmer or user.)
    public var visibleColumnCount:int;
    public var visibleHeaderCount:int;
    public var visibleRowCount:int;
    // Indices of visible rows and columns.
    // These are null when nothing is filtered, for performance reasons.
    protected var visibleRowIndices:Vector.<int>;
    protected var visibleColumnIndices:Vector.<int>;
    // The highest valid childID.
    public var maxChildID:int;
    // True if we are in cell navigation mode (single or multiple selection).
    public var isCellMode:Boolean;
    // True if we are in a multiple selection mode (row or cell).
    public var isMultiSelect:Boolean;
    // True if the data in this object is invalid for some reason.
    // Usually this means an invalid childID was passed to setup().
    public var isInvalid:Boolean;
    // True if the given childID represents a column header cell.
    public var isColumnHeader:Boolean;
    // 0-based indices of row and column in the sets of visible ones.
    public var visibleColumnIndex:int;
    public var visibleRowIndex:int;
    // 0-based indices of row and column in the set of all of each.
    public var columnIndex:int;
    public var rowIndex:int;

    private function childIDFromVisibleRowAndColumn(visibleRowIndex:int, visibleColumnIndex:int):uint
    {
        var childID:int = visibleHeaderCount + 1;
        if (visibleRowIndex < 0)
            childID = 0;
        else if (isCellMode)
            if (visibleColumnIndex < 0)
                childID = 0;
            else
                childID += visibleRowIndex * visibleColumnCount + visibleColumnIndex;
        else
            childID += visibleRowIndex;
        return uint(childID);
    }

    public function childIDFromRowAndColumn(rowIndex:int, columnIndex:int):uint
    {
        return childIDFromVisibleRowAndColumn(
            visibleRowIndices == null ? rowIndex : visibleRowIndices.indexOf(rowIndex),
            visibleColumnIndices == null ? columnIndex : visibleColumnIndices.indexOf(columnIndex)
        );
    }

    private function childIDOutOfBounds(childID: int):Boolean
    {
        if (int(childID) <= 0)
            return true;
        if (!dataGrid.dataProvider || !dataGrid.columns)
            return true
        if (childID > maxChildID)
            return true;
        return false;
    }

    public function boundingRect():Object
    {
        // First see if this item is on screen.
        // We could skip this, but we'd run the risk of having
        // assistive technology create huge numbers of itemRenderers below
        // by quickly scanning an entire grid.
        if (!isColumnHeader && (rowIndex < 0 || rowIndex >= rowCount))
            // Also covers rowCount == 0 effectively.
            return null;
        if (isCellMode && (columnIndex < 0 || columnIndex >= columnCount))
            return null;
        var vri:Vector.<int> = dataGrid.grid.getVisibleRowIndices();
        var vci:Vector.<int> = dataGrid.grid.getVisibleColumnIndices();
        if (isColumnHeader && vci.indexOf(columnIndex) < 0)
            return null;
        if ((!isColumnHeader && vri.indexOf(rowIndex) < 0)
        || (isCellMode && vci.indexOf(columnIndex) < 0))
            return null;

        var result:Object;
        if (isColumnHeader)
        {
            result = dataGrid.columnHeaderBar.getHeaderRendererAt(columnIndex);
        }
        else if (isCellMode)
        {
            result = dataGrid.grid.getItemRendererAt(rowIndex, columnIndex);
        }
        else  // row mode
        {
            // Use the item renderers at both ends of this row
            // to calculate the width.
            // We assume here that top and bottom of all renderers for one row are equal.
            var r1:Object = dataGrid.grid.getItemRendererAt(rowIndex, vci[0]);
            var r2:Object = dataGrid.grid.getItemRendererAt(rowIndex, vci[vci.length-1]);
            var xy:Point = new Point(
                r1.getLayoutBoundsX(),
                r1.getLayoutBoundsY()
            );
            xy = dataGrid.grid.localToGlobal(xy);
            xy = dataGrid.globalToLocal(xy);
            result = new Rectangle(
                xy.x, xy.y,
                r2.getLayoutBoundsX() + r2.getLayoutBoundsWidth() - r1.getLayoutBoundsX(),
                r1.getLayoutBoundsHeight()
            );
        }
        return result;
    }

}
