package taberion;

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.lang.*;
import java.math.*;

public class TPanel extends JPanel{
private TTableModel myTableModel;
private TCellSize myCellSize;
private Color myMaxColor, myMinColor;
private int myParseState;


    public TPanel (TTableModel tableModel)
    {
        super();

        this.setModel(tableModel);
        myMaxColor = TConsts.startMaxCol;
        myMinColor = TConsts.startMinCol;
        myCellSize = new TCellSize(2, 2);
    }

    public void paint(Graphics graphics)
    {
        //just for background painting
        super.paint(graphics);
/**///        //System.out.println("PAINT");

        Graphics2D graphics2d = (Graphics2D)graphics;

        //the size of this panel
        //won't be seen complete, but can be scrolled
        this.setPreferredSize(new Dimension((int)(getModel().getColumnCount()*getCellSize().getWidth()), (int)(getModel().getRowCount()*getCellSize().getHeight())));

        Rectangle tmpRect = this.getVisibleRect();

        /*prints only the area which can be seen by the user
         */


        BigDecimal maxVal = new BigDecimal(this.getModel().getMaxValue());
        BigDecimal minVal = new BigDecimal(this.getModel().getMinValue());

        int startCol = (int)Math.floor(tmpRect.getX()/getCellSize().getWidth());
        int startRow = (int)Math.floor(tmpRect.getY()/getCellSize().getHeight());

        Point paintPos = new Point((int)Math.floor(startCol*getCellSize().getWidth()), (int)Math.floor(startRow*getCellSize().getHeight()));

/**///        //System.out.println("Curr Size for 1 Cell " + getCellSize());

        if (this.getCellSize().getHeight()>=1.0d && this.getCellSize().getWidth()>=1.0d)
        {

            for(int j=startRow; j < getModel().getRowCount() && (paintPos.getY() < (tmpRect.getHeight()+tmpRect.getY())); j++)
            {
                for(int i=startCol; i < getModel().getColumnCount() && (paintPos.getX() < (tmpRect.getWidth()+tmpRect.getX())); i++)
                {
                    String tmpStr = (String)getModel().getValueAt(j, i);
                    BigDecimal tmpDec = new BigDecimal(tmpStr);
                    tmpDec = tmpDec.subtract(minVal);
                    if (maxVal.subtract(minVal).compareTo(new BigDecimal("0"))==0)
                    {
                        tmpDec = new BigDecimal(0);
                    }else{
                        tmpDec = tmpDec.divide(maxVal.subtract(minVal), 5, BigDecimal.ROUND_HALF_UP);
                    }
                    graphics2d.setColor(TColorCreator.getColorFromRange(myMaxColor, myMinColor, tmpDec.floatValue()));
                    graphics2d.fillRect((int)paintPos.getX(), (int)paintPos.getY(), (int)Math.round(getCellSize().getWidth()), (int)Math.round(getCellSize().getHeight()));

                    paintPos.translate((int)Math.round(getCellSize().getWidth()), 0);
                }
                paintPos.setLocation(startCol*getCellSize().getWidth(), (int)(paintPos.getY()));

                paintPos.translate(0, (int)Math.round(getCellSize().getHeight()));
            }
        }
        else
        {
            int columnCount = (int)Math.ceil(1 / this.getCellSize().getWidth());
            int rowCount = (int)Math.ceil(1 / this.getCellSize().getHeight());

/**///            //System.out.println("Should take together: "+columnCount + " " + rowCount);

            for(int j=startRow; j < getModel().getRowCount() && (paintPos.getY() < (tmpRect.getHeight()+tmpRect.getY())); j+=rowCount)
            {
                for(int i=startCol; i < getModel().getColumnCount() && (paintPos.getX() < (tmpRect.getWidth()+tmpRect.getX())); i+=columnCount)
                {
                    String tmpStr = (String)getModel().getValueAt(j, i);

                    BigDecimal tmpDec = new BigDecimal(tmpStr);


//System.out.println("Calculation from " + i + ", "+ j + " size: " + columnCount + ", " + rowCount);
                    tmpDec = calcAverage(i, j, columnCount, rowCount);
                    tmpDec = tmpDec.subtract(minVal);
                    tmpDec = tmpDec.divide(maxVal.subtract(minVal), 5, BigDecimal.ROUND_HALF_UP);
                    graphics2d.setColor(TColorCreator.getColorFromRange(myMaxColor, myMinColor, tmpDec.floatValue()));
                    graphics2d.fillRect((int)paintPos.getX(), (int)paintPos.getY(), (int)Math.round(getCellSize().getWidth()*columnCount), (int)Math.round(getCellSize().getHeight()*rowCount));

                    paintPos.translate((int)Math.round(getCellSize().getWidth()), 0);
                }
                paintPos.setLocation(startCol*getCellSize().getWidth()*columnCount, (int)(paintPos.getY()));

                paintPos.translate(0, (int)Math.round(getCellSize().getHeight()*rowCount));
            }
        }


        //needed to update the ScrollPane's bars
        this.revalidate();
    }

    public void setModel(TTableModel tablemodel)
    {
        myTableModel = tablemodel;

    }

    public TTableModel getModel()
    {
        return myTableModel;
    }

    public void setBackground(Color color)
    {
        super.setBackground(color);
    }

    public void setCellSize(TCellSize s)
    {
        this.myCellSize = s;
    }

    public TCellSize getCellSize()
    {
        return myCellSize;
    }

    public void setColorRange(Color max, Color min)
    {
        myMaxColor = max;
        myMinColor = min;
        repaint();
    }

    public Point getMiddleViewCell()
    {
        Rectangle tmpRect = this.getVisibleRect();
        Point middlePos = new Point((int)(tmpRect.getX()+tmpRect.getWidth()/2), (int)(tmpRect.getY()+tmpRect.getHeight()/2));
/**///        //System.out.println(middlePos);

        int xCellPos, yCellPos;

        xCellPos = (int)(middlePos.getX()/this.getCellSize().getWidth());
        yCellPos = (int)(middlePos.getY()/this.getCellSize().getHeight());

/**///        //System.out.println("Panel: CurrPos " + new Point(xCellPos, yCellPos) );

        return new Point(xCellPos, yCellPos);
    }

    public Point getCellPos(Point cellPos)
    {
        Point tmpPoint = new Point((int)(this.getCellSize().getWidth()*cellPos.getX()),
                (int)(this.getCellSize().getHeight()*cellPos.getY()));
/**///        //System.out.println("Panel: CellPos " +tmpPoint);
        return tmpPoint;
    }

    public TCellSize calculateNewCellSize()
    {
        TCellSize tmpSize = new TCellSize();
        Rectangle tmpRect = this.getVisibleRect();
/**///        //System.out.println(tmpRect);
        tmpSize.setSize((tmpRect.getWidth()/getModel().getColumnCount()),
                       (tmpRect.getHeight()/getModel().getRowCount()) );

        if (tmpSize.getWidth()==0.0d)
        {
            tmpSize.translate(1.0d, 0.0d);
        }
        if (tmpSize.getHeight()==0.0d)
        {
            tmpSize.translate(0.0d, 1.0d);
        }

        this.setCellSize(tmpSize);

        return tmpSize;
    }

    public BigDecimal calcAverage(int xPos, int yPos, int width, int height)
    {
//        //System.out.println("START");
        int counter = (width) * (height);
        BigDecimal myBigDec = new BigDecimal(0d);

//        //System.out.println("Counter: " + counter);

        for(int x = xPos; x < (xPos + width) && x < getModel().getColumnCount(); x++)
        {
            for (int y = yPos; y < (yPos + height) && y < getModel().getRowCount(); y++)
            {
                myBigDec = myBigDec.add(new BigDecimal(getModel().getValueAt(y, x).toString()));
            }
        }

        myBigDec = myBigDec.divide(new BigDecimal(Integer.toString(counter)), BigDecimal.ROUND_HALF_UP);

//        //System.out.println("STOP");

        return myBigDec;
    }

    /** Changes the type, how the content is displayed
     */
    public void setParseState(int pS)
    {
        this.myParseState=pS;
    }

    /** Returns the type, how the content is displayed
     */
    public int getParseState()
    {
        return myParseState;
    }
}