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

const sceneSetup = () => {
    let _editor: MaterialEditor | undefined;
    let _database: Database | undefined;
    const _material = ref<PhysicalMaterialRecord>(new PhysicalMaterialRecord());
    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 = computed(() => _material.value);
    const CurrentShowObject = computed(() => _editor.ShowObject);

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

        // 初始化Database
        _database = new Database();
        _database.hm.Enable = false; // 关闭历史记录功能
        Material.value.Name = _database.MaterialTable.AllocateName(); // 使用Database为材质分配材质名
        _database.MaterialTable.Add(Material.value as PhysicalMaterialRecord);

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

        _editor = new MaterialEditor();
        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.SetSize(canvas.clientWidth, canvas.clientHeight);
            view.UpdateRender();
        }
    }

    function Dispose() {
        Material.value.GoodBye();
        _editor?.Dispose();
        _editor = undefined;
        _database.Destroy();
        _database = undefined;
        window.onresize = undefined;
    }

    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() {
        // TODO: Danger: 如果等待下面这一行，会导致更新卡住（未知问题）
        Material.value.Update();
        // Material.value.Material.needsUpdate = true;
        await _editor.Update();
        Update();
    }

    async function ChangeTextureFromUrlAsync(url?: string) {
        // 关联贴图
        const db = Material.value.Db;
        if (!db) return; // 材质未初始化
        let record = Material.value.map?.Object as TextureTableRecord;
        if (!record) {
            // record = db.TextureTable.Symbols.values().next().value;
            // if(!record){
            record = new TextureTableRecord();
            record.Name = db.TextureTable.AllocateName();
            db.TextureTable.Add(record);
            // 替换map
            Material.value.map = record.Id;
            // Material.value.map = img ? record.Id : undefined;
            // }
        }

        // record.objectId = new ObjectId(undefined, record);
        _currTexture.value = record['texture'] as Texture;
        if (url) {
            record.imageUrl = url;
            _currTexture.value.image = undefined;
        }

        // 设置Store
        if (!_currTexture.value.image) {
            const img = await LoadImageFromUrl(GetConfig().host + '/' + record.imageUrl);
            _currTexture.value.image = img;
            _currTexture.value.needsUpdate = true;
        }
        await UpdateMaterialAsync();
    }

    async function SerializeMaterialAsync() {
        const matJson = MaterialOut(Material.value as PhysicalMaterialRecord);
        console.log(matJson);
        return matJson;
    }

    async function ImportMaterialAsync(materialJson: string) {
        const material = MaterialIn(JSON.parse(materialJson));
        _material.value = material;
        _editor.setMaterial(_material.value as PhysicalMaterialRecord);
        await ChangeTextureFromUrlAsync();
        await UpdateMaterialAsync();
    }

    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,
        CurrTexture,
        Geometries,
        Material,
        Initial,
        Update,
        UpdateMaterialAsync,
        ChangeTextureFromUrlAsync,
        SerializeMaterialAsync,
        ImportMaterialAsync,
        GenerateMaterialLogoAsync,
        Dispose,
        CurrentShowObject,
        GetEditor: () => _editor
    };
};

export const useScene = defineStore('scene', sceneSetup);
export const useSceneRaw = defineStore('sceneRaw', sceneSetup); // 独立场景，用来静默执行材质序列化

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