package space.animefu.starfallhaven;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/** Platform-neutral drag selection used by the touch view. Coordinates are tile units. */
final class AreaDesignation {
    enum Shape { RECTANGLE, LINE }

    static final class TilePoint {
        final int x, y;
        TilePoint(int x, int y) { this.x=x; this.y=y; }
        @Override public boolean equals(Object other) {
            if (!(other instanceof TilePoint)) return false;
            TilePoint p=(TilePoint)other;
            return x==p.x && y==p.y;
        }
        @Override public int hashCode() { return x*31+y; }
    }

    private int startX=-1, startY=-1, endX=-1, endY=-1;
    private Shape shape=Shape.RECTANGLE;

    void begin(int x,int y,Shape requested) {
        shape=requested==null?Shape.RECTANGLE:requested;
        startX=endX=clamp(x,0,GameWorld.WIDTH-1);
        startY=endY=clamp(y,0,GameWorld.HEIGHT-1);
    }

    void update(int x,int y) {
        if (!active()) return;
        endX=clamp(x,0,GameWorld.WIDTH-1);
        endY=clamp(y,0,GameWorld.HEIGHT-1);
    }

    void clear() { startX=startY=endX=endY=-1; }
    boolean active() { return startX>=0; }
    int left() { return Math.min(startX,endX); }
    int top() { return Math.min(startY,endY); }
    int right() { return Math.max(startX,endX); }
    int bottom() { return Math.max(startY,endY); }

    List<TilePoint> tiles() {
        if (!active()) return Collections.emptyList();
        ArrayList<TilePoint> out=new ArrayList<>();
        if (shape==Shape.RECTANGLE) {
            for(int y=top();y<=bottom();y++) for(int x=left();x<=right();x++) out.add(new TilePoint(x,y));
        } else {
            // A mobile-friendly orthogonal line: lock to the dominant drag axis.
            if (Math.abs(endX-startX)>=Math.abs(endY-startY)) {
                int from=Math.min(startX,endX),to=Math.max(startX,endX);
                for(int x=from;x<=to;x++) out.add(new TilePoint(x,startY));
            } else {
                int from=Math.min(startY,endY),to=Math.max(startY,endY);
                for(int y=from;y<=to;y++) out.add(new TilePoint(startX,y));
            }
        }
        return out;
    }

    private static int clamp(int value,int low,int high) { return Math.max(low,Math.min(high,value)); }
}
