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 ZigzagSelecter extends TwoCornersRouteSelecter {

    private Point routes[][];

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

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

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

        // right, left
        for(int i = 2; i <= width; i++){
            int len = i * height - 1;
            Point[] rightUp   = new Point[len];
            Point[] rightDown = new Point[len];
            Point[] leftUp    = new Point[len];
            Point[] leftDown  = new Point[len];
            for(int j = 0; j < len; j++){
                int h = (j + 1) / i;
                if(h % 2 == 0){
                    rightUp[j]   = new Point(  (j + 1) % i ,  (j + 1) / i);
                    rightDown[j] = new Point(  (j + 1) % i , -(j + 1) / i);
                    leftUp[j]    = new Point(-((j + 1) % i),  (j + 1) / i);
                    leftDown[j]  = new Point(-((j + 1) % i), -(j + 1) / i);
                }else{
                    rightUp[j]   = new Point(  i - 1 - (j + 1) % i ,  (j + 1) / i);
                    rightDown[j] = new Point(  i - 1 - (j + 1) % i , -(j + 1) / i);
                    leftUp[j]    = new Point(-(i - 1 - (j + 1) % i),  (j + 1) / i);
                    leftDown[j]  = new Point(-(i - 1 - (j + 1) % i), -(j + 1) / i);
                }
            }
            
            routes.add(rightUp);
            routes.add(rightDown);
            routes.add(leftUp);
            routes.add(leftDown);
        }
        
        // up, down
        for(int i = 2; i <= height; i++){
            int len = i * width - 1;
            Point[] upRight   = new Point[len];
            Point[] upLeft    = new Point[len];
            Point[] downRight = new Point[len];
            Point[] downLeft  = new Point[len];
            for(int j = 0; j < len; j++){
                int h = (j + 1) / i;
                if(h % 2 == 0){
                    upRight[j]   = new Point( (j + 1) / i,   (j + 1) % i );
                    upLeft[j]    = new Point(-(j + 1) / i,   (j + 1) % i );
                    downRight[j] = new Point( (j + 1) / i, -((j + 1) % i));
                    downLeft[j]  = new Point(-(j + 1) / i, -((j + 1) % i));
                }else{
                    upRight[j]   = new Point( (j + 1) / i,   i - 1 - (j + 1) % i );
                    upLeft[j]    = new Point(-(j + 1) / i,   i - 1 - (j + 1) % i );
                    downRight[j] = new Point( (j + 1) / i, -(i - 1 - (j + 1) % i));
                    downLeft[j]  = new Point(-(j + 1) / i, -(i - 1 - (j + 1) % i));
                }
            }
            
            routes.add(upRight);
            routes.add(upLeft);
            routes.add(downRight);
            routes.add(downLeft);
        }
        
        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 this.routes.length + super.getNumOfRoutes();
    }

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