package jp.ac.nii.icpc2010.players;

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import jp.ac.nii.icpc2010.playfield.IPlayField;

// Player that moves to the point from which the longest hilbert curve can be drawn.
public class TwoCornersRouteSelecter extends BaseRouteSelecter {

    private Point routes[][];

    public TwoCornersRouteSelecter(int id, IPlayField playField) {
        super(id, playField);

        List<Point[]> routes = new ArrayList<Point[]>();

        int width = Math.min(playField.getWidth(), 32);
        int height = Math.min(playField.getHeight(), 32);

        // right, left
        for(int i = 0; i < width - 1; i++){
            for(int j = 0; j < height - 1; j++){
                int len = i + j + width;

                Point[] rightUpRight   = new Point[len];
                Point[] rightUpLeft    = new Point[len];
                Point[] rightDownRight = new Point[len];
                Point[] rightDownLeft  = new Point[len];
                Point[] leftUpRight    = new Point[len];
                Point[] leftUpLeft     = new Point[len];
                Point[] leftDownRight  = new Point[len];
                Point[] leftDownLeft   = new Point[len];

                for(int k = 0; k < i; k++){
                    rightUpRight[k] = rightUpLeft[k] = rightDownRight[k] = rightDownLeft[k] = new Point(  k + 1 , 0);
                    leftUpRight[k]  = leftUpLeft[k]  = leftDownRight[k]  = leftDownLeft[k]  = new Point(-(k + 1), 0);
                }
                for(int k = 0; k < j; k++){
                    rightUpRight[i + k]   = rightUpLeft[i + k]   = new Point( i,   k + 1);
                    rightDownRight[i + k] = rightDownLeft[i + k] = new Point( i, -(k + 1));
                    leftUpRight[i + k]    = leftUpLeft[i + k]    = new Point(-i,   k + 1);
                    leftDownRight[i + k]  = leftDownLeft[i + k]  = new Point(-i, -(k + 1));
                }
                for(int k = 0; k < width; k++){
                    rightUpRight[i + j + k]   = new Point( i + k,  j);
                    rightDownRight[i + j + k] = new Point( i + k, -j);
                    leftUpRight[i + j + k]    = new Point(-i + k,  j);
                    leftDownRight[i + j + k]  = new Point(-i + k, -j);
                    rightUpLeft[i + j + k]    = new Point( i - k,  j);
                    rightDownLeft[i + j + k]  = new Point( i - k, -j);
                    leftUpLeft[i + j + k]     = new Point(-i - k,  j);
                    leftDownLeft[i + j + k]   = new Point(-i - k, -j);                   
                }

                routes.add(rightUpRight);
                routes.add(rightUpLeft);
                routes.add(rightDownRight);
                routes.add(rightDownLeft);
                routes.add(leftUpRight);
                routes.add(leftUpLeft);
                routes.add(leftDownRight);
                routes.add(leftDownLeft);
            }
        }

        // up, down
        for(int i = 0; i < height - 1; i++){
            for(int j = 0; j < width - 1; j++){
                int len = i + j + height;

                Point[] upRightUp     = new Point[len];
                Point[] upRightDown   = new Point[len];
                Point[] upLeftUp      = new Point[len];
                Point[] upLeftDown    = new Point[len];
                Point[] downRightUp   = new Point[len];
                Point[] downRightDown = new Point[len];
                Point[] downLeftUp    = new Point[len];
                Point[] downLeftDown  = new Point[len];

                for(int k = 0; k < i; k++){
                    upRightUp[k]   = upRightDown[k]   = upLeftUp[k]   = upLeftDown[k]   = new Point(0,   k + 1);
                    downRightUp[k] = downRightDown[k] = downLeftUp[k] = downLeftDown[k] = new Point(0, -(k + 1));
                }
                for(int k = 0; k < j; k++){
                    upRightUp[i + k]   = upRightDown[i + k]   = new Point(  k + 1 ,  i);
                    upLeftUp[i + k]    = upLeftDown[i + k]    = new Point(-(k + 1),  i);
                    downRightUp[i + k] = downRightDown[i + k] = new Point(  k + 1 , -i);
                    downLeftUp[i + k]  = downLeftDown[i + k]  = new Point(-(k + 1), -i);
                }
                for(int k = 0; k < height; k++){
                    upRightUp[i + j + k]     = new Point( j,  i + k);
                    upLeftUp[i + j + k]      = new Point(-j,  i + k);
                    downRightUp[i + j + k]   = new Point( j, -i + k);
                    downLeftUp[i + j + k]    = new Point(-j, -i + k);
                    upRightDown[i + j + k]   = new Point( j,  i - k);
                    upLeftDown[i + j + k]    = new Point(-j,  i - k);
                    downRightDown[i + j + k] = new Point( j, -i - k);
                    downLeftDown[i + j + k]  = new Point(-j, -i - k);                   
                }

                routes.add(upRightUp);
                routes.add(upRightDown);
                routes.add(upLeftUp);
                routes.add(upLeftDown);
                routes.add(downRightUp);
                routes.add(downRightDown);
                routes.add(downLeftUp);
                routes.add(downLeftDown);
            }
        }

        this.routes = new Point[routes.size()][];
        for(int i = 0; i < this.routes.length; i++){
            this.routes[i] = routes.get(i);
        }
    }

    @Override
    protected int getNumOfRoutes() {
        return super.getNumOfRoutes() + this.routes.length;
    }

    @Override
    protected Point[] getRoute(int routeId) {
        if(routeId < super.getNumOfRoutes()){
            return super.getRoute(routeId);
        }else{
            return this.routes[routeId - super.getNumOfRoutes()];
        }
    }
}
