// SPDX-License-Identifier: AGPL-3.0-or-later
package preservation;

/** Effect-only selected CheckCollision port from pinned src/dra/collider.c.
 * Used ONLY by Rebound Stone. Existing EnemyTerrain behavior is unchanged.
 * Original defined slopes, recursive neighbor effects and special types are
 * retained, including the source initialized-NONE fallthrough for unused
 * extended byte types. Values outside the byte domain report unsupported and
 * block rather than silently treating unidentified geometry as empty. No correction sensors
 * or unrelated entity collision physics are claimed by this effect query.
 */
public final class ReboundTerrain {
    static final class Collision {int effects,code;boolean unsupported;}
    private ReboundTerrain(){}
    static Collision query(StageMap.Room room,int x,int y){return query(room,x,y,false);}
    static Collision query(StageMap.Room room,int x,int y,boolean recursive){
        int code=x<0||x>=room.width||y<0||y>=room.height?0:room.codeAt(x,y);Collision out=new Collision();out.code=code;
        if(code<0||code>255){out.effects=3;out.unsupported=true;return out;}if(code<128){out.effects=code&3;return out;}int t=code-128,fx=15-(x&15),fy=15-(y&15),offset=0;
        switch(t){
        case 1:case 2:case 10:case 11:case 24:case 25:
            if(recursive)out.effects=1;else{Collision above=query(room,x,y-(y&15)-1,true);out.unsupported=above.unsupported;out.effects=(above.effects&0x8000)!=0?above.effects|3:0x8003;}break;
        case 5:case 6:case 16:case 17:case 34:case 35:
            if(recursive)out.effects=1;else{Collision below=query(room,x,y+16-(y&15),true);out.unsupported=below.unsupported;out.effects=(below.effects&0x800)!=0?below.effects|3:0x803;}break;
        case 0:out.effects=0x8000|(fx+fy<16?1:0);break;
        case 3:out.effects=0xC000|(fx>=fy?1:0);break;
        case 8:case 9:offset=t==8?16:0;out.effects=0x9000|(fx+offset+fy*2<32?1:0);break;
        case 12:case 13:offset=t==12?16:0;out.effects=0xD000|(fx+offset>=fy*2?1:0);break;
        case 20:case 21:case 22:case 23:offset=(23-t)*16;out.effects=0xA000|(fx+offset+fy*4<64?1:0);break;
        case 26:case 27:case 28:case 29:offset=(29-t)*16;out.effects=0xE000|(fx+offset>=fy*4?1:0);break;
        case 4:out.effects=0x800|(fx<=fy?1:0);break;
        case 7:out.effects=0x4800|(fx+fy>14?1:0);break;
        case 14:case 15:offset=t==14?16:0;out.effects=0x1800|(fx+offset<=fy*2?1:0);break;
        case 18:case 19:offset=t==18?16:0;out.effects=0x5800|(fx+offset+fy*2>29?1:0);break;
        case 30:case 31:case 32:case 33:offset=(33-t)*16;out.effects=0x2800|(fx+offset<=fy*4?1:0);break;
        case 36:case 37:case 38:case 39:offset=(39-t)*16;out.effects=0x6800|(fx+offset+fy*4>59?1:0);break;
        case 127:out.effects=fy<8?3:0;break;case 126:out.effects=fy>=8?3:0;break;
        case 125:out.effects=fy<8?1:0;break;case 124:out.effects=fy>=8?1:0;break;
        case 123:out.effects=4;break;case 122:out.effects=fy<8?4:0;break;
        case 121:out.effects=fy<8?8:0;break;case 120:out.effects=19;break;
        case 119:case 118:case 117:case 116:out.effects=32;break;
        case 115:case 114:case 113:case 112:case 111:case 110:out.effects=3;break;
        case 109:out.effects=8;break;case 108:case 107:break;
        case 106:out.effects=fy>=8?8:0;break;case 105:out.effects=fy>=8?4:0;break;
        case 104:out.effects=fy<8?65:0;break;case 103:out.effects=fy>=8?65:0;break;
        case 102:out.effects=fy<8?129:0;break;case 101:out.effects=fy>=8?129:0;break;
        default:out.effects=0;break;
        }return out;
    }
}
