import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import { LoadingManagerWrapper } from './loading-manager';

// Instantiate a loader
const loader = new GLTFLoader(LoadingManagerWrapper.getInstance().manager);

// Optional: Provide a DRACOLoader instance to decode compressed mesh data
const dracoLoader = new DRACOLoader(
  LoadingManagerWrapper.getInstance().manager,
);
dracoLoader.setDecoderPath('/examples/js/libs/draco/');
loader.setDRACOLoader(dracoLoader);

let instance: PonyModelLoader;

export class PonyModelLoader {
  public ponyModel!: THREE.Group;
  public animations!: THREE.AnimationClip[];

  initialize(): Promise<THREE.Group> {
    return new Promise((resolve, reject) => {
      // Load a glTF resource
      loader.load(
        // resource URL
        '/assets/clean-pony2fix.glb',
        // called when the resource is loaded
        (gltf) => {
          this.ponyModel = gltf.scene;
          this.animations = gltf.animations;
          // temp: disable frustum culling for eyes
          this.ponyModel.children[0].children[2].frustumCulled = false;

          resolve(gltf.scene);

          // gltf.animations; // Array<THREE.AnimationClip>
          // gltf.scene; // THREE.Group
          // gltf.scenes; // Array<THREE.Group>
          // gltf.cameras; // Array<THREE.Camera>
          // gltf.asset; // Object
        },
        // called while loading is progressing
        (xhr) => {
          console.log((xhr.loaded / xhr.total) * 100 + '% loaded');
        },
        // called when loading has errors
        (error) => {
          console.log('An error happened');
          reject(error);
        },
      );
    });
  }

  public static getInstance(): PonyModelLoader {
    if (!instance) {
      instance = new PonyModelLoader();
    }
    return instance;
  }
}
