import java.awt.*;

/** A class used to create Persian Rugs.
    **/

public class PersianRugMaker {
  private Color [] colors;
  private int [] [] rug;  //indices into colors
  private int rugSize;
  private RugSpecs rgspcs;
  private int borderColor;

    /** Creates a PersianRugMaker.  The sides will
        have length (2^x) + 1. A good value to try for x is 8.
        Initially, white will be
        the only color used.  If you want to use more colors, you
        will have to use the addColor method before calling
        makeRug().
        * @param x The exponent to use in determining the size
        * @param f The RugFunction to use in computing the colors
     **/
    public PersianRugMaker(int x, RugSpecs rgspcs){
        rugSize = (int) Math.pow(2, x) + 1;
        rug = new int[rugSize][rugSize];
        borderColor = rgspcs.getBorderColor();
        this.rgspcs = rgspcs;
        colors = new Color[rgspcs.colorListLength()];
        for (int i = 0; i < rgspcs.colorListLength(); i++)
          colors[i] = rgspcs.getColor(i);
    }

  /** Creates a window with the rug in it using the given colors,
    size, and rug function. 
    */
  public void makeRug(){
    Color [] [] cols = privMakeRug();
    RugCanvas rc = new RugCanvas(cols);
    RugFrame rf = new RugFrame(rc);
  }
  
  private Color [] [] privMakeRug(){

    for (int i = 0; i<rugSize; i++){
      rug[i][0] = borderColor;
      rug[i][rugSize-1] = borderColor;
      rug[0][i] = borderColor;
      rug[rugSize-1][i] = borderColor;
    }
    
    // ok then, now we do it
    
    doRug(0, 0, rugSize-1, rugSize-1);
    
    Color [] [] out = new Color[rugSize][rugSize];
    
    for (int i = 0; i<rugSize; i++){
      for (int j = 0; j<rugSize; j++){
        out[i][j] = colors[rug[i][j]];
      }
    }
    
    return out;
    
  }
  
  private void doRug(int aX, int aY, int bX, int bY){
    // figure out the color
    
    if (bX - aX == 1)
      return;
    
    int newColor = rgspcs.newColor(rug[aX][aY], rug[bX][aY],
                                   rug[bX][bY], rug[aX][bY]);
    
    newColor %= colors.length;
    
    if (newColor < 0){
      newColor *= -1;
    }
    
    // now, fill in the inside
    
    int halfX = ((bX - aX) / 2) + aX;
    
    for (int i = aY + 1; i<bY; i++){
      rug[halfX][i] = newColor;
    }
    
    int halfY = ((bY - aY) / 2) + aY;
    
    for (int i = aX + 1; i < bX; i++){
      rug[i][halfY] = newColor;
    }
    
    // now, recur on each box
    
    doRug(aX, aY, halfX, halfY);
    doRug(halfX, aY, bX, halfY);
    doRug(aX, halfY, halfX, bY);
    doRug(halfX, halfY, bX, bY);
  }
}