import { BinaryDataType } from "../../../../../core/binary/type/BinaryDataType.js";
import { apply_texture_clamping_to_coordinate } from "../texture/apply_texture_clamping_to_coordinate.js";
import { vec3_uint8_to_float } from "../vec3_uint8_to_float.js";
import { TextureFilter } from "./TextureFilter.js";
import { TextureWrapping } from "./TextureWrapping.js";

let id_counter = 0;

export class StandardTexture {
    id = id_counter++;

    /**
     * @type {Sampler2D}
     */
    sampler
    magFilter = TextureFilter.LinearFilter
    type = BinaryDataType.Uint8
    wrapS = TextureWrapping.ClampToEdgeWrapping
    wrapT = TextureWrapping.ClampToEdgeWrapping

    /**
     *
     * @param {StandardTexture} other
     */
    copy(other) {
        this.sampler = other.sampler
        this.magFilter = other.magFilter
        this.type = other.type
        this.wrapS = other.wrapS
        this.wrapT = other.wrapT
    }

    clone() {
        const r = new StandardTexture();

        r.copy(this);

        return r;
    }

    /**
     *
     * @param {Sampler2D} sampler
     * @returns {StandardTexture}
     */
    static from(sampler) {
        const texture = new StandardTexture();

        texture.sampler = sampler;

        return texture;
    }

    /**
     *
     * @param {number[]|Float32Array} out
     * @param {number} u
     * @param {number} v
     */
    sample(out, u, v) {

        const _u = apply_texture_clamping_to_coordinate(this.wrapS, u);
        const _v = apply_texture_clamping_to_coordinate(this.wrapT, v);


        const magFilter = this.magFilter;

        const sampler = this.sampler;

        switch (magFilter) {
            default:
            case TextureFilter.NearestFilter:
            case TextureFilter.NearestMipMapLinearFilter:
                sampler.sampleNearestUV(_u, _v, out);
                break;

            case TextureFilter.LinearFilter:
            case TextureFilter.LinearMipmapLinearFilter:

                sampler.sampleBilinearUV(_u, _v, out);
                break;
        }

        if (this.type === BinaryDataType.Uint8) {
            vec3_uint8_to_float(out, out);
        }
    }
}