/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package top.r3944realms.eroticdungeongame.mixin.bendylib;

import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import io.github.kosmx.bendylib.ICuboidBuilder;
import io.github.kosmx.bendylib.impl.BendableCuboid;
import io.github.kosmx.bendylib.impl.RememberingPos;
import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.Shadow;

import java.util.Collection;
import java.util.HashMap;

@Pseudo
@Mixin(
        value = {BendableCuboid.Builder.class},
        remap = false
)
public abstract class MixinBendableCuboidBuilder {
    @Shadow abstract RememberingPos getOrCreate(HashMap<Vector3f, RememberingPos> positions, Vector3f pos);

    @Shadow abstract Vector3f transformVector(Vector3f pos, Vector3f vectorU, Vector3f vectorV, int u1, int v1, int u2, int v2, int u, int v);

    @WrapMethod(
            method = {"createAndAddQuads"}
    )
    private void injectedHead(
            Collection<BendableCuboid.Quad> quads, HashMap<Vector3f, RememberingPos> positions, Vector3f[] edges, int u1, int v1, int u2, int v2, float squishU, float squishV, boolean flip, ICuboidBuilder.Data data, Operation<Void> original
    ) {
        int ud = Math.abs(u2 - u1);
        int vd = Math.abs(v1 - v2);
        int vdd3 = vd / 3;
        if (vdd3 == 0) {
            vdd3 = 1;
        }

        while(vd % vdd3 != 0) {
            --vdd3;
        }

        int rUd = u2 < u1 ? ud : -ud;
        int rVdd3 = v1 < v2 ? vdd3 : -vdd3;

        for(int i = u2; i != u1; i += rUd) {
            for(int j = v1; j != v2; j += rVdd3) {
                int rUdOffset = i + rUd;
                int rVdd3Offset = j + rVdd3;
                RememberingPos pos1 = this.getOrCreate(positions, this.transformVector(new Vector3f(edges[0]), new Vector3f(edges[1]), new Vector3f(edges[2]), u2, v1, u1, v2, rUdOffset, j));
                RememberingPos pos2 = this.getOrCreate(positions, this.transformVector(new Vector3f(edges[0]), new Vector3f(edges[1]), new Vector3f(edges[2]), u2, v1, u1, v2, rUdOffset, rVdd3Offset));
                RememberingPos pos3 = this.getOrCreate(positions, this.transformVector(new Vector3f(edges[0]), new Vector3f(edges[1]), new Vector3f(edges[2]), u2, v1, u1, v2, i, rVdd3Offset));
                RememberingPos pos4 = this.getOrCreate(positions, this.transformVector(new Vector3f(edges[0]), new Vector3f(edges[1]), new Vector3f(edges[2]), u2, v1, u1, v2, i, j));
                quads.add(new BendableCuboid.Quad(new RememberingPos[]{pos4, pos1, pos2, pos3}, (float) rUdOffset, (float) j, (float) i, (float) rVdd3Offset, (float)data.textureWidth, (float)data.textureHeight, data.mirror));
            }
        }
    }
}
