<template>
    <div vertical class="material-adjuster">
        <div class="adjust-section">
            <h3>操作</h3>
            <fieldset v-if="debugMode" style="margin: 1em 0;">
                <legend>DEBUG</legend>
                <label>上传路径ID</label>
                <input v-model="materialInfo.dirId" type="text" placeholder="材质路径ID" />
            </fieldset>
            <label>材质名</label>
            <input v-model.trim="materialInfo.materialName" type="text" placeholder="材质名" />

            <!-- <CfFlex gap="1em">
                <button class="btn-success" style="min-width: 110px;" @click="HandleUpload">上传</button>
                <button class="btn-danger" style="min-width: 110px;" @click="HandleCancel">取消</button>
            </CfFlex> -->
        </div>

        <div class="adjust-section">
            <h3>模型预览</h3>
            <label>选择模型样式</label>
            <select v-model="CurrGeometry">
                <option v-for="name in Geometries" :value="name">{{ name }}</option>
            </select>
        </div>
        <div class="adjust-section" v-if="debugMode">
            <h3>纹理选择（DEBUG）</h3>
            <label>纹理链接</label>
            <input v-model.trim="_textureSrc" type="text" placeholder="在此键入纹理图像的URL..." />
            <button class="btn-primary" @click="scene.ChangeTextureAsync(_textureSrc)"
                style="margin-left: 1em;">应用</button>
        </div>
        <div class="adjust-section">
            <h3>材质调节</h3>

            <label>金属度</label>
            <CfFlex gap="1em">
                <input v-model="model.metallic" type="range" min="0" max="1" step="0.01" />
                <span>{{ model.metallic }}</span>
            </CfFlex>

            <label>粗糙度</label>
            <CfFlex gap="1em">
                <input v-model="model.roughness" type="range" min="0" max="1" step="0.01" />
                <span>{{ model.roughness }}</span>
            </CfFlex>

            <label>法线强度</label>
            <CfFlex gap="1em">
                <input v-model="model.normalScale" type="range" min="0" max="1" step="0.01" />
                <span>{{ model.normalScale }}</span>
            </CfFlex>

            <label>高光</label>
            <CfFlex gap="1em">
                <input v-model="model.emissiveIntensity" type="range" min="0" max="1" step="0.01" />
                <span>{{ model.emissiveIntensity }}</span>
            </CfFlex>
        </div>

        <div class="adjust-section">
            <h3>纹理调节</h3>
            <label>启用纹理</label>
            <input type="checkbox" v-model="enableTexture" />

            <label>平铺U</label>
            <select v-model="textureAdjustment.wrapS">
                <option value="0">镜像平铺</option>
                <option value="1">平铺</option>
                <option value="2">展开</option>
            </select>

            <label>平铺V</label>
            <select v-model="textureAdjustment.wrapT">
                <option value="0">镜像平铺</option>
                <option value="1">平铺</option>
                <option value="2">展开</option>
            </select>

            <label>旋转</label>
            <input v-model="textureAdjustment.rotation" type="number" step="0.01" min="0" max="359" />

            <div>
                <label>偏移</label>
                <span style="margin-right: 0.5em;">X</span>
                <input v-model="textureAdjustment.moveX" type="number" step="0.01" style="max-width: 60px;" />
                &NonBreakingSpace;
                &NonBreakingSpace;
                <span style="margin-right: 0.5em;">Y</span>
                <input v-model="textureAdjustment.moveY" type="number" step="0.01" style="max-width: 60px;" />
            </div>

            <div>
                <label>尺寸</label>
                <span style="margin-right: 0.5em;">长</span>
                <input v-model="textureAdjustment.repeatX" type="number" step="0.01" style="max-width: 60px;" />
                &NonBreakingSpace;
                &NonBreakingSpace;
                <span style="margin-right: 0.5em;">宽</span>
                <input v-model="textureAdjustment.repeatY" type="number" step="0.01" style="max-width: 60px;" />
            </div>

        </div>
    </div>
</template>

<script setup lang='ts'>
import { ref, reactive, watch, onMounted } from "vue"
import { useScene, type TextureAdjustment } from "../stores/sceneStore";
import { storeToRefs } from "pinia";
import CfFlex from "./CfFlex.vue";
import { DirectoryId } from "../api/Request";
import { IsNullOrWhitespace } from "../helpers/helper.string";
import { DeflateAsync } from "../helpers/helper.compression";

export interface MaterialRequest {
    /** 材质名 */
    name: string;
    /** 材质logo文件 */
    logo: Blob;
    /** 序列化并Deflate压缩后的材质文件的Base64编码 */
    file: string;
}

const scene = useScene();

const props = defineProps<{
    textureSrc?: string;
}>();
const emits = defineEmits<{
    (e: 'cancel'): void;
    (e: 'submit', data: MaterialRequest): void; 
}>();

const debugMode = ref(false);
const { CurrGeometry, Geometries, Material } = storeToRefs(scene);
const enableTexture = ref(Material.value.useMap);
const _textureSrc = ref(props.textureSrc);
const textureAdjustment = reactive<TextureAdjustment>({
    wrapS: 0,
    wrapT: 0,
    rotation: 0,
    repeatX: 1,
    repeatY: 1,
    moveX: 0,
    moveY: 0
});
const uploading = ref(false);
const model = reactive({
    metallic: Material.value.matalness,
    roughness: Material.value.roughness,
    normalScale: Material.value.bumpScale,
    emissiveIntensity: Material.value.specular
});
const materialInfo = reactive({
    dirId: DirectoryId.MaterialDir, // 正常来说是2
    materialName: ''
});

onMounted(() => {
    scene.ChangeTextureAsync(_textureSrc.value);
})

watch(() => props.textureSrc, async (val) => {
    _textureSrc.value = val;
    await scene.ChangeTextureAsync(_textureSrc.value);
});

watch(model, async (val) => {
    await UpdateMaterial();
});

watch(enableTexture, async (val) => {
    await EnableTexture(val);
});

watch(textureAdjustment, async (val) => {
    UpdateTexture();
});

async function UpdateMaterial() {
    Material.value.matalness = model.metallic;
    Material.value.roughness = model.roughness;
    Material.value.bumpScale = model.normalScale;
    Material.value.specular = model.emissiveIntensity;
    // Material.value.side = DoubleSide;
    await scene.UpdateMaterialAsync();
}

function UpdateTexture() {
    scene.UpdateTexture(textureAdjustment);
}

async function EnableTexture(enable: boolean) {
    Material.value.useMap = enable;
    await scene.UpdateMaterialAsync();
}

async function HandleUpload() {
    try {
        if (IsNullOrWhitespace(materialInfo.materialName)) {
            alert('材质名称不可为空');
            return;
        }

        uploading.value = true;
        const data = {
            name: materialInfo.materialName,
            logo: await scene.GenerateMaterialLogoAsync(),
            // jsonString -> Deflate -> BinaryString -> Base64
            file: btoa(String.fromCharCode(...await DeflateAsync(await scene.SerializeMaterialAsync())))
        };
        emits('submit', data);
        return data;
    } finally {
        uploading.value = false;
    }
}

function HandleCancel() {
    emits('cancel');
}

defineExpose({
    Upload: HandleUpload,
    Cancel: HandleCancel
})

</script>

<style scoped>
.material-adjuster
{
    padding: 1rem;
    overflow-y: auto;
}

.adjust-section
{
    border-radius: 8px;
    border: 1px solid #ccc;
    padding: 1rem;
    margin-bottom: 1rem;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    background-color: white;
}

h3
{
    margin: 0 0 0.5rem 0;
}

label
{
    display: block;
}

select
{
    width: 220px;
    padding: 4px;
    margin: 0.5rem 0;
}

input[type="range"]
{
    width: 220px;
    margin: 0.5rem 0;
}

input[type="text"]
{
    width: 220px;
    padding: 4px;
    margin: 0.5rem 0;
}

input[type="number"]
{
    width: 220px;
    padding: 4px;
    margin: 0.5rem 0;
}

.btn-success
{
    background-color: #4caf50;
    color: white;
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.btn-success:hover
{
    background-color: #3e8e41;
}

.btn-danger
{
    background-color: #f44336;
    color: white;
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.btn-danger:hover
{
    background-color: #da190b;
}

.btn-primary
{
    background-color: #2196f3;
    color: white;
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.btn-primary:hover
{
    background-color: #0a7ed2;
}
</style>