import { planesEqual } from "./planesEqual.js";
import { isArraysEqualWithComparator } from "../../../../core/collection/array/isArraysEqualWithComparator.js";
import { computeTextureEqualityById } from "./computeTextureEqualityById.js";

/**
 * NOTE: does not do deep comparison on textures, only checks the IDs
 * @param {Material|MeshStandardMaterial|MeshDepthMaterial|MeshMatcapMaterial} a
 * @param {Material|MeshStandardMaterial|MeshDepthMaterial|MeshMatcapMaterial} b
 * @returns {boolean}
 */
export function computeMaterialEquality(a, b) {
    if (a === b) {
        return true;
    }

    if (a.type !== b.type) {
        return false;
    }

    if (
        a.alphaTest !== b.alphaTest
        || a.blendDst !== b.blendDst
        || a.blendDstAlpha !== b.blendDstAlpha
        || a.blendEquation !== b.blendEquation
        || a.blendEquationAlpha !== b.blendEquationAlpha
        || a.blending !== b.blending
        || a.blendSrc !== b.blendSrc
        || a.blendSrcAlpha !== b.blendSrcAlpha
        || a.clipIntersection !== b.clipIntersection
        || !isArraysEqualWithComparator(a.clippingPlanes, b.clippingPlanes, planesEqual)
        || a.clipShadows !== b.clipShadows
        || a.colorWrite !== b.colorWrite
        || a.depthFunc !== b.depthFunc
        || a.depthTest !== b.depthTest
        || a.depthWrite !== b.depthWrite
        || a.fog !== b.fog
        || a.lights !== b.lights
        || a.opacity !== b.opacity
        || a.polygonOffset !== b.polygonOffset
        || a.polygonOffsetFactor !== b.polygonOffsetFactor
        || a.polygonOffsetUnits !== b.polygonOffsetUnits
        || a.precision !== b.precision
        || a.premultipliedAlpha !== b.premultipliedAlpha
        || a.dithering !== b.dithering
        || a.flatShading !== b.flatShading
        || a.side !== b.side
        || a.transparent !== b.transparent
        || a.vertexColors !== b.vertexColors
        || a.visible !== b.visible
    ) {
        return false;
    }

    //check "onBeforeCompile" property
    if (a.onBeforeCompile !== b.onBeforeCompile) {
        return false;
    }

    if (a.isMeshStandardMaterial) {
        if (
            !a.color.equals(b.color)
            || a.roughness !== b.roughness
            || a.metalness !== b.metalness
            || a.lightMapIntensity !== b.lightMapIntensity
            || a.aoMapIntensity !== b.aoMapIntensity
            || !a.emissive.equals(b.emissive)
            || a.emissiveIntensity !== b.emissiveIntensity
            || a.bumpScale !== b.bumpScale
            || a.normalMapType !== b.normalMapType
            || !a.normalScale.equals(b.normalScale)
            || a.displacementScale !== b.displacementScale
            || a.displacementBias !== b.displacementBias
            || a.envMapIntensity !== b.envMapIntensity
            || a.refractionRatio !== b.refractionRatio
            || a.wireframe !== b.wireframe
            || a.wireframeLinewidth !== b.wireframeLinewidth
            || a.morphTargets !== b.morphTargets
            || a.morphNormals !== b.morphNormals
            || !computeTextureEqualityById(a.roughnessMap, b.roughnessMap)
            || !computeTextureEqualityById(a.metalnessMap, b.metalnessMap)
            || !computeTextureEqualityById(a.alphaMap, b.alphaMap)
            || !computeTextureEqualityById(a.envMap, b.envMap)
            || !computeTextureEqualityById(a.displacementMap, b.displacementMap)
            || !computeTextureEqualityById(a.normalMap, b.normalMap)
            || !computeTextureEqualityById(a.emissiveMap, b.emissiveMap)
            || !computeTextureEqualityById(a.bumpMap, b.bumpMap)
            || !computeTextureEqualityById(a.aoMap, b.aoMap)
            || !computeTextureEqualityById(a.map, b.map)
            || !computeTextureEqualityById(a.lightMap, b.lightMap)
        ) {
            return false;
        }
    } else if (a.isMeshDepthMaterial) {
        if (
            !computeTextureEqualityById(a.alphaMap, b.alphaMap)
            || a.depthPacking !== b.depthPacking
            || !computeTextureEqualityById(a.displacementMap, b.displacementMap)
            || a.displacementScale !== b.displacementScale
            || a.displacementBias !== b.displacementBias
            || !computeTextureEqualityById(a.map, b.map)
            || a.morphTargets !== b.morphTargets
            || a.wireframe !== b.wireframe
            || a.wireframeLinewidth !== b.wireframeLinewidth
        ) {
            return false;
        }
    } else if (a.isMeshMatcapMaterial) {
        if (
            !a.color.equals(b.color)
            || !computeTextureEqualityById(a.matcap, b.matcap)
            || !computeTextureEqualityById(a.map, b.map)
            || !computeTextureEqualityById(a.bumpMap, b.bumpMap)
            || !computeTextureEqualityById(a.normalMap, b.normalMap)
            || !a.normalScale.equals(b.normalScale)
            || !computeTextureEqualityById(a.displacementMap, b.displacementMap)
            || a.displacementScale !== b.displacementScale
            || a.displacementBias !== b.displacementBias
            || !computeTextureEqualityById(a.alphaMap, b.alphaMap)
            || a.morphTargets !== b.morphTargets
            || a.morphNormals !== b.morphNormals
            || a.flatShading !== b.flatShading
        ) {
            return false;
        }
    } else {
        //TODO implement other material types
        return false;
    }

    return true;
}
