package cnp.ew.scrolling;

import java.awt.*;

import cnp.ew.util.*;
import cnp.ew.lightweight.*;

public abstract class CpVariableCellSizeScrollable extends CpAbstractScrollable
{
    Point locationInCells = new Point(0, 0);

    public Point cellToPoint(int cellX, int cellY)
    {
        // Could speed up by looking at the scrolled location

        int x = 0;
        int y = 0;
        for (int i = 0; i < cellX; i++) {
            x += getCellWidth(i);
        }
        for (int i = 0; i < cellY; i++) {
            y += getCellHeight(i);
        }
        return new Point(x, y);
    }


    public Point cellToPoint(Point p)
    {
        return cellToPoint(p.x, p.y);
    }

    public Point pointToCell(int px, int py)
    {
        Dimension sizeInCells = getSizeInCells();
        int c;
        int r;
        int x = 0;
        for (c = 0; c < sizeInCells.width; c++) {
            x += getCellWidth(c);
            if (px < x) {
                break;
            }
        }
        int y = 0;
        for (r = 0; r < sizeInCells.height; r++) {
            y += getCellHeight(r);
            if (py < y) {
                break;
            }
        }
        return new Point(c, r);
    }


    // hmmm.... when is this relevent Issue:  Should we size these huge?  would it matter?  Scrolling is
    //   based on cell sizes not size?  more efficient that constantly recalcing or keeping track of...
    // ........ No one calls this yet.
    public Dimension recomputeSize()
    {
        //Issue.  This should return size, or set it.  Not both.
        resize(10000, 10000);
        return new Dimension(10000, 10000);
    }



    public Point getLocationInCells()
    {
        return locationInCells;
    }

    public void setLocationInCells(Point newLocation)
    {
        locationInCells = newLocation;
    }

    public Dimension getScrollerSizeInCells(Dimension scrollerSize)
    {
        Dimension sizeInCells = getSizeInCells();
        int widthInCells = 0, heightInCells = 0;

        int dim = 0;
        for (int y = locationInCells.y; y < sizeInCells.height; y++) {
            dim += getCellHeight(y);
            heightInCells = y - locationInCells.y;
            if (dim > scrollerSize.height) {
                break;
            }
        }
        if (dim <= scrollerSize.height) {
            heightInCells++;
        }

        dim = 0;
        for (int x = locationInCells.x; x < sizeInCells.width; x++) {
            dim += getCellWidth(x);
            widthInCells = x - locationInCells.x;
            if (dim > scrollerSize.width) {
                break;
            }
        }
        if (dim <= scrollerSize.width) {
            widthInCells++;
        }
        return new Dimension(widthInCells, heightInCells);
    }

    // This changes when the scrollable sizes, or a particular cell sizes
    public Point getMaximumScrollPosition(Dimension scrollerSize)
    {
        Dimension sizeInCells = getSizeInCells();
        Point lastCell = new Point(sizeInCells.width - 1, sizeInCells.height - 1);

        int dim = 0;
        int maxY;
        for (maxY = lastCell.y; maxY > 0; maxY--) {
            dim += getCellHeight(maxY);
            if (dim > scrollerSize.height) {
                break;
            }
        }

        dim = 0;
        int maxX;
        for (maxX = lastCell.x; maxX > 0; maxX--) {
            dim += getCellWidth(maxX);
            if (dim > scrollerSize.width) {
                break;
            }
        }
        return new Point(maxX + 1, maxY + 1);
    }


    public Dimension deltaBetween(Point from, Point to)
    {
        int deltaX, deltaY;

        int start = Math.min(from.y, to.y);
        int end = Math.max(from.y, to.y);
        int dim = 0;
        for (int i = start; i < end; i++) {
            dim += getCellHeight(i);
        }
        if (from.y < to.y) {
            deltaY = -dim;
        } else {
            deltaY = dim;
        }
        start = Math.min(from.x, to.x);
        end = Math.max(from.x, to.x);
        dim = 0;
        for (int i = start; i < end; i++) {
            dim += getCellWidth(i);
        }
        if (from.x < to.x) {
            deltaX = -dim;
        } else {
            deltaX = dim;
        }
        return new Dimension(deltaX, deltaY);
    }

    public Dimension getCellSize()
    {
        // This is an error

        // ISSUE:  How do we report errors?  Like CpErrorManager.error("");
        return null;
    }

}



