import { defineStore } from "pinia";
import { computed, ref } from "vue";
import { MaterialEditor } from "../common/MaterialEditor";
import { ObjectId, PhysicalMaterialRecord, TextureTableRecord } from "webcad_ue4_api";
import { LoadImageFromUrl } from "../helpers/helper.imageLoader";
import { Texture } from "three";
import { materialRenderer } from "../common/MaterialRenderer";
import { MaterialOut } from "../common/MaterialSerializer";

export const useScene = defineStore('scene', () => {
    let _editor: MaterialEditor;
    const _currGeometry = ref<string>('球');
    const _currTexture = ref<Texture>();
    const CurrGeometry = computed({
        get: () => _currGeometry.value,
        set: (val: string) => ChangeGeometry(val)
    })
    const CurrTexture = computed<Texture>(() => _currTexture.value);
    const Geometries = ref<string[]>([]);
    const Material = ref<PhysicalMaterialRecord>(new PhysicalMaterialRecord());

    function Initial(canvas: HTMLElement) {
        if (_editor) {
            console.warn("SceneStore has already been initialized");
            return;
        }

        // 为Material配置一个ObjectId，否则其无法被序列化
        Material.value.objectId = new ObjectId(undefined, undefined);

        _editor = MaterialEditor.GetInstance();
        Geometries.value = Array.from(_editor.Geometrys.keys());
        _currGeometry.value = _editor.CurGeometryName;

        _editor.SetViewer(canvas);
        _editor.setMaterial((Material.value) as PhysicalMaterialRecord);

        const view = _editor.Viewer;
        window.onresize = () => {
            view.OnSize(canvas.clientWidth, canvas.clientHeight);
            view.UpdateRender();
        }
    }

    function ChangeGeometry(geoName: string) {
        _currGeometry.value = geoName;
        let geo = _editor.Geometrys.get(_currGeometry.value);
        if (geo) {
            _editor.ShowMesh.geometry = geo;
            _editor.Viewer.UpdateRender();
        }
    }

    function Update() {
        _editor.Viewer.UpdateRender();
    }

    async function UpdateMaterialAsync() {
        await Material.value.Update();
        await _editor.Update();
        Update();
    }

    async function ChangeTextureAsync(url: string) {
        const record = new TextureTableRecord();
        record.objectId = new ObjectId(undefined, record);

        const img = await LoadImageFromUrl(url);

        _currTexture.value = record['texture'] as Texture;
        _currTexture.value.image = img;
        Material.value.map = img ? record.Id : undefined;
        _currTexture.value.needsUpdate = true;
        await UpdateMaterialAsync();
    }

    function UpdateTexture(adjustment: TextureAdjustment) {
        const texture = _currTexture.value;
        texture.wrapS = adjustment.wrapS;
        texture.wrapT = adjustment.wrapT;
        texture.anisotropy = 16;
        texture.rotation = adjustment.rotation;
        texture.repeat.set(adjustment.repeatX, adjustment.repeatY);
        texture.offset.set(adjustment.moveX, adjustment.moveY);
        texture.needsUpdate = true;

        Update();
    }

    async function SerializeMaterialAsync() {
        // TODO: Warn: 是否要生成logo路径？
        // const logoPath = await HandleUpdateLogo(); 
        const matJson = MaterialOut(Material.value as PhysicalMaterialRecord);
        return matJson;
    }

    async function GenerateMaterialLogoAsync() {
        const blob = await materialRenderer.getBlob(Material.value.Material);
        return blob;
        // const file = new File([blob], "blob.png", { type: blob.type });

        // const formData = new FormData();
        // formData.append("file", file);

        // let data = await Post(ImgsUrl.logo, formData);

        // let logoPath = "";
        // if (data.err_code === RequestStatus.Ok) {
        //     logoPath = data.images.path;
        // }
        // return logoPath;
    }

    return {
        CurrGeometry,
        Geometries,
        Material,
        Initial,
        Update,
        UpdateMaterialAsync,
        ChangeTextureAsync,
        UpdateTexture,
        SerializeMaterialAsync,
        GenerateMaterialLogoAsync
    };
});

export type TextureAdjustment = {
    wrapS: number,
    wrapT: number,
    rotation: number,
    repeatX: number,
    repeatY: number,
    moveX: number,
    moveY: number
}
export interface UploadMaterialRequest {
    dirId: string;
    materialName: string;
}