/*
 * Basis Loader
 *
 * Usage:
 * // basis_loader.js should be loaded from the same directory as
 * // basis_transcoder.js and basis_transcoder.wasm
 *
 * // Create the texture loader and set the WebGL context it should use. Spawns
 * // a worker which handles all of the transcoding.
 * let basisLoader = new BasisLoader();
 * basisLoader.setWebGLContext(gl);
 *
 * // To allow separate color and alpha textures to be returned in cases where
 * // it would provide higher quality:
 * basisLoader.allowSeparateAlpha = true;
 *
 * // loadFromUrl() returns a promise which resolves to a completed WebGL
 * // texture or rejects if there's an error loading.
 * basisBasics.loadFromUrl(fullPathToTexture).then((result) => {
 *   // WebGL color+alpha texture;
 *   result.texture;
 *
 *   // WebGL alpha texture, only if basisLoader.allowSeparateAlpha is true.
 *   // null if alpha is encoded in result.texture or result.alpha is false.
 *   result.alphaTexture;
 *
 *   // True if the texture contained an alpha channel.
 *   result.alpha;
 *
 *   // Number of mip levels in texture/alphaTexture
 *   result.mipLevels;
 *
 *   // Dimensions of the base mip level.
 *   result.width;
 *   result.height;
 * });
 */

// This file contains the code both for the main thread interface and the
// worker that does the transcoding.
const IN_WORKER = typeof importScripts === "function";
const SCRIPT_PATH = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;

if (!IN_WORKER) {
  //
  // Main Thread
  //
  class PendingTextureRequest {
    constructor(gl, url) {
      this.gl = gl;
      this.url = url;
      this.texture = null;
      this.alphaTexture = null;
      this.promise = new Promise((resolve, reject) => {
        this.resolve = resolve;
        this.reject = reject;
      });
    }

    uploadImageData(webglFormat, buffer, mipLevels) {
      let gl = this.gl;
      let texture = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, texture);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, mipLevels.length > 1 || webglFormat.uncompressed ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);

      let levelData = null;

      for (let mipLevel of mipLevels) {
        if (!webglFormat.uncompressed) {
          levelData = new Uint8Array(buffer, mipLevel.offset, mipLevel.size);
          gl.compressedTexImage2D(
            gl.TEXTURE_2D,
            mipLevel.level,
            webglFormat.format,
            mipLevel.width,
            mipLevel.height,
            0,
            levelData);
        } else {
          switch (webglFormat.type) {
            case WebGLRenderingContext.UNSIGNED_SHORT_4_4_4_4:
            case WebGLRenderingContext.UNSIGNED_SHORT_5_5_5_1:
            case WebGLRenderingContext.UNSIGNED_SHORT_5_6_5:
              levelData = new Uint16Array(buffer, mipLevel.offset, mipLevel.size / 2);
              break;
            default:
              levelData = new Uint8Array(buffer, mipLevel.offset, mipLevel.size);
              break;
          }
          gl.texImage2D(
            gl.TEXTURE_2D,
            mipLevel.level,
            webglFormat.format,
            mipLevel.width,
            mipLevel.height,
            0,
            webglFormat.format,
            webglFormat.type,
            levelData);
        }
      }

      if (webglFormat.uncompressed && mipLevels.length == 1) {
        gl.generateMipmap(gl.TEXTURE_2D);
      }

      return texture;
    }
  };

  class BasisLoader {
    constructor() {
      this.gl = null;
      this.supportedFormats = {};
      this.pendingTextures = {};
      this.nextPendingTextureId = 1;
      this.allowSeparateAlpha = false;

      // Reload the current script as a worker
      this.worker = new Worker(SCRIPT_PATH);
      this.worker.onmessage = (msg) => {
        // Find the pending texture associated with the data we just received
        // from the worker.
        let pendingTexture = this.pendingTextures[msg.data.id];
        if (!pendingTexture) {
          if (msg.data.error) {
            console.error(`Basis transcode failed: ${msg.data.error}`);
          }
          console.error(`Invalid pending texture ID: ${msg.data.id}`);
          return;
        }

        // Remove the pending texture from the waiting list.
        delete this.pendingTextures[msg.data.id];

        // If the worker indicated an error has occured handle it now.
        if (msg.data.error) {
          console.error(`Basis transcode failed: ${msg.data.error}`);
          pendingTexture.reject(`${msg.data.error}`);
          return;
        }

        // Upload the image data returned by the worker.
        pendingTexture.texture = pendingTexture.uploadImageData(
            msg.data.webglFormat,
            msg.data.buffer,
            msg.data.mipLevels);

        if (msg.data.alphaBuffer) {
          pendingTexture.alphaTexture = pendingTexture.uploadImageData(
              msg.data.webglFormat,
              msg.data.alphaBuffer,
              msg.data.mipLevels);
        }

        pendingTexture.resolve({
          mipLevels: msg.data.mipLevels.length,
          width: msg.data.mipLevels[0].width,
          height: msg.data.mipLevels[0].height,
          alpha: msg.data.hasAlpha,
          texture: pendingTexture.texture,
          alphaTexture: pendingTexture.alphaTexture,
        });
      };
    }

    setWebGLContext(gl) {
      if (this.gl != gl) {
        this.gl = gl;
        if (gl) {
          this.supportedFormats = {
            s3tc: !!gl.getExtension('WEBGL_compressed_texture_s3tc'),
            etc1: !!gl.getExtension('WEBGL_compressed_texture_etc1'),
            etc2: !!gl.getExtension('WEBGL_compressed_texture_etc'),
            pvrtc: !!gl.getExtension('WEBGL_compressed_texture_pvrtc'),
            astc: !!gl.getExtension('WEBGL_compressed_texture_astc'),
            bptc: !!gl.getExtension('EXT_texture_compression_bptc')
          };
        } else {
          this.supportedFormats = {};
        }
      }
    }

    // This method changes the active texture unit's TEXTURE_2D binding
    // immediately prior to resolving the returned promise.
    loadFromUrl(url) {
      let pendingTexture = new PendingTextureRequest(this.gl, url);
      this.pendingTextures[this.nextPendingTextureId] = pendingTexture;

      this.worker.postMessage({
        id: this.nextPendingTextureId,
        url: url,
        allowSeparateAlpha: this.allowSeparateAlpha,
        supportedFormats: this.supportedFormats
      });

      this.nextPendingTextureId++;
      return pendingTexture.promise;
    }
  }

  window.BasisLoader = BasisLoader;

} else {
  //
  // Worker
  //
  importScripts('basis_transcoder.js');

  let BasisFile = null;

  const BASIS_INITIALIZED = BASIS().then((module) => {
    BasisFile = module.BasisFile;
    module.initializeBasis();
  });

  // Copied from enum class transcoder_texture_format in basisu_transcoder.h with minor javascript-ification
  const BASIS_FORMAT = {
    // Compressed formats

    // ETC1-2
    cTFETC1_RGB: 0,							// Opaque only, returns RGB or alpha data if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
    cTFETC2_RGBA: 1,							// Opaque+alpha, ETC2_EAC_A8 block followed by a ETC1 block, alpha channel will be opaque for opaque .basis files

    // BC1-5, BC7 (desktop, some mobile devices)
    cTFBC1_RGB: 2,							// Opaque only, no punchthrough alpha support yet, transcodes alpha slice if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
    cTFBC3_RGBA: 3, 							// Opaque+alpha, BC4 followed by a BC1 block, alpha channel will be opaque for opaque .basis files
    cTFBC4_R: 4,								// Red only, alpha slice is transcoded to output if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
    cTFBC5_RG: 5,								// XY: Two BC4 blocks, X=R and Y=Alpha, .basis file should have alpha data (if not Y will be all 255's)
    cTFBC7_RGBA: 6,							// RGB or RGBA, mode 5 for ETC1S, modes (1,2,3,5,6,7) for UASTC

    // PVRTC1 4bpp (mobile, PowerVR devices)
    cTFPVRTC1_4_RGB: 8,						// Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified, nearly lowest quality of any texture format.
    cTFPVRTC1_4_RGBA: 9,					// Opaque+alpha, most useful for simple opacity maps. If .basis file doesn't have alpha cTFPVRTC1_4_RGB will be used instead. Lowest quality of any supported texture format.

    // ASTC (mobile, Intel devices, hopefully all desktop GPU's one day)
    cTFASTC_4x4_RGBA: 10,					// Opaque+alpha, ASTC 4x4, alpha channel will be opaque for opaque .basis files. Transcoder uses RGB/RGBA/L/LA modes, void extent, and up to two ([0,47] and [0,255]) endpoint precisions.

    // Uncompressed (raw pixel) formats
    cTFRGBA32: 13,							// 32bpp RGBA image stored in raster (not block) order in memory, R is first byte, A is last byte.
    cTFRGB565: 14,							// 166pp RGB image stored in raster (not block) order in memory, R at bit position 11
    cTFBGR565: 15,							// 16bpp RGB image stored in raster (not block) order in memory, R at bit position 0
    cTFRGBA4444: 16,							// 16bpp RGBA image stored in raster (not block) order in memory, R at bit position 12, A at bit position 0

    cTFTotalTextureFormats: 22,
  };

  // WebGL compressed formats types, from:
  // http://www.khronos.org/registry/webgl/extensions/

  // https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
  const COMPRESSED_RGB_S3TC_DXT1_EXT  = 0x83F0;
  const COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
  const COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
  const COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;

  // https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/
  const COMPRESSED_RGB_ETC1_WEBGL = 0x8D64

  // https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc/
  const COMPRESSED_R11_EAC                        = 0x9270;
  const COMPRESSED_SIGNED_R11_EAC                 = 0x9271;
  const COMPRESSED_RG11_EAC                       = 0x9272;
  const COMPRESSED_SIGNED_RG11_EAC                = 0x9273;
  const COMPRESSED_RGB8_ETC2                      = 0x9274;
  const COMPRESSED_SRGB8_ETC2                     = 0x9275;
  const COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2  = 0x9276;
  const COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277;
  const COMPRESSED_RGBA8_ETC2_EAC                 = 0x9278;
  const COMPRESSED_SRGB8_ALPHA8_ETC2_EAC          = 0x9279;

  // https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_astc/
  const COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0;

  // https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/
  const COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
  const COMPRESSED_RGB_PVRTC_2BPPV1_IMG  = 0x8C01;
  const COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
  const COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;

  // https://www.khronos.org/registry/webgl/extensions/EXT_texture_compression_bptc/
  const COMPRESSED_RGBA_BPTC_UNORM_EXT = 0x8E8C;
  const COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT = 0x8E8D;
  const COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT = 0x8E8E;
  const COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT = 0x8E8F;

  const BASIS_WEBGL_FORMAT_MAP = {};
  // Compressed formats
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFBC1_RGB] = { format: COMPRESSED_RGB_S3TC_DXT1_EXT };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFBC3_RGBA] = { format: COMPRESSED_RGBA_S3TC_DXT5_EXT };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFBC7_RGBA] = { format: COMPRESSED_RGBA_BPTC_UNORM_EXT };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFETC1_RGB] = { format: COMPRESSED_RGB_ETC1_WEBGL };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFETC2_RGBA] = { format: COMPRESSED_RGBA8_ETC2_EAC };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFASTC_4x4_RGBA] = { format: COMPRESSED_RGBA_ASTC_4x4_KHR };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFPVRTC1_4_RGB] = { format: COMPRESSED_RGB_PVRTC_4BPPV1_IMG };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFPVRTC1_4_RGBA] = { format: COMPRESSED_RGBA_PVRTC_4BPPV1_IMG };

  // Uncompressed formats
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFRGBA32] = { uncompressed: true, format: WebGLRenderingContext.RGBA, type: WebGLRenderingContext.UNSIGNED_BYTE };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFRGB565] = { uncompressed: true, format: WebGLRenderingContext.RGB, type: WebGLRenderingContext.UNSIGNED_SHORT_5_6_5 };
  BASIS_WEBGL_FORMAT_MAP[BASIS_FORMAT.cTFRGBA4444] = { uncompressed: true, format: WebGLRenderingContext.RGBA, type: WebGLRenderingContext.UNSIGNED_SHORT_4_4_4_4 };

  // Notifies the main thread when a texture has failed to load for any reason.
  function fail(id, errorMsg) {
    postMessage({
      id: id,
      error: errorMsg
    });
  }

  function basisFileFail(id, basisFile, errorMsg) {
    fail(id, errorMsg);
    basisFile.close();
    basisFile.delete();
  }

  // This utility currently only transcodes the first image in the file.
  const IMAGE_INDEX = 0;
  const TOP_LEVEL_MIP = 0;

  function transcode(id, arrayBuffer, supportedFormats, allowSeparateAlpha) {
    let basisData = new Uint8Array(arrayBuffer);

    let basisFile = new BasisFile(basisData);
    let images = basisFile.getNumImages();
    let levels = basisFile.getNumLevels(IMAGE_INDEX);
    let hasAlpha = basisFile.getHasAlpha();
    if (!images || !levels) {
      basisFileFail(id, basisFile, 'Invalid Basis data');
      return;
    }

    if (!basisFile.startTranscoding()) {
      basisFileFail(id, basisFile, 'startTranscoding failed');
      return;
    }

    let basisFormat = undefined;
    let needsSecondaryAlpha = false;
    if (hasAlpha) {
      if (supportedFormats.etc2) {
        basisFormat = BASIS_FORMAT.cTFETC2_RGBA;
      } else if (supportedFormats.bptc) {
        basisFormat = BASIS_FORMAT.cTFBC7_RGBA;
      } else if (supportedFormats.s3tc) {
        basisFormat = BASIS_FORMAT.cTFBC3_RGBA;
      } else if (supportedFormats.astc) {
        basisFormat = BASIS_FORMAT.cTFASTC_4x4_RGBA;
      } else if (supportedFormats.pvrtc) {
        if (allowSeparateAlpha) {
          basisFormat = BASIS_FORMAT.cTFPVRTC1_4_RGB;
        } else {
          basisFormat = BASIS_FORMAT.cTFPVRTC1_4_RGBA;
        }
      } else if (supportedFormats.etc1 && allowSeparateAlpha) {
        basisFormat = BASIS_FORMAT.cTFETC1_RGB;
        needsSecondaryAlpha = true;
      } else {
        // If we don't support any appropriate compressed formats transcode to
        // raw pixels. This is something of a last resort, because the GPU
        // upload will be significantly slower and take a lot more memory, but
        // at least it prevents you from needing to store a fallback JPG/PNG and
        // the download size will still likely be smaller.
        basisFormat = BASIS_FORMAT.RGBA32;
      }
    } else {
      if (supportedFormats.etc1) {
        // Should be the highest quality, so use when available.
        // http://richg42.blogspot.com/2018/05/basis-universal-gpu-texture-format.html
        basisFormat = BASIS_FORMAT.cTFETC1_RGB;
      } else if (supportedFormats.bptc) {
        basisFormat = BASIS_FORMAT.cTFBC7_RGBA;
      } else if (supportedFormats.s3tc) {
        basisFormat = BASIS_FORMAT.cTFBC1_RGB;
      } else if (supportedFormats.etc2) {
        basisFormat = BASIS_FORMAT.cTFETC2_RGBA;
      } else if (supportedFormats.astc) {
        basisFormat = BASIS_FORMAT.cTFASTC_4x4_RGBA;
      } else if (supportedFormats.pvrtc) {
        basisFormat = BASIS_FORMAT.cTFPVRTC1_4_RGB;
      } else {
        // See note on uncompressed transcode above.
        basisFormat = BASIS_FORMAT.cTFRGB565;
      }
    }

    if (basisFormat === undefined) {
      basisFileFail(id, basisFile, 'No supported transcode formats');
      return;
    }

    let webglFormat = BASIS_WEBGL_FORMAT_MAP[basisFormat];

    // If we're not using compressed textures it'll be cheaper to generate
    // mipmaps on the fly, so only transcode a single level.
    if (webglFormat.uncompressed) {
      levels = 1;
    }

    // Gather information about each mip level to be transcoded.
    let mipLevels = [];
    let totalTranscodeSize = 0;

    for (let mipLevel = 0; mipLevel < levels; ++mipLevel) {
      let transcodeSize = basisFile.getImageTranscodedSizeInBytes(IMAGE_INDEX, mipLevel, basisFormat);
      mipLevels.push({
        level: mipLevel,
        offset: totalTranscodeSize,
        size: transcodeSize,
        width: basisFile.getImageWidth(IMAGE_INDEX, mipLevel),
        height: basisFile.getImageHeight(IMAGE_INDEX, mipLevel),
      });
      totalTranscodeSize += transcodeSize;
    }

    // Allocate a buffer large enough to hold all of the transcoded mip levels at once.
    let transcodeData = new Uint8Array(totalTranscodeSize);
    let alphaTranscodeData = needsSecondaryAlpha ? new Uint8Array(totalTranscodeSize) : null;

    // Transcode each mip level into the appropriate section of the overall buffer.
    for (let mipLevel of mipLevels) {
      let levelData = new Uint8Array(transcodeData.buffer, mipLevel.offset, mipLevel.size);
      if (!basisFile.transcodeImage(levelData, IMAGE_INDEX, mipLevel.level, basisFormat, 1, 0)) {
        basisFileFail(id, basisFile, 'transcodeImage failed');
        return;
      }
      if (needsSecondaryAlpha) {
        let alphaLevelData = new Uint8Array(alphaTranscodeData.buffer, mipLevel.offset, mipLevel.size);
        if (!basisFile.transcodeImage(alphaLevelData, IMAGE_INDEX, mipLevel.level, basisFormat, 1, 1)) {
          basisFileFail(id, basisFile, 'alpha transcodeImage failed');
          return;
        }
      }
    }

    basisFile.close();
    basisFile.delete();

    // Post the transcoded results back to the main thread.
    let transferList = [transcodeData.buffer];
    if (needsSecondaryAlpha) {
      transferList.push(alphaTranscodeData.buffer);
    }
    postMessage({
      id: id,
      buffer: transcodeData.buffer,
      alphaBuffer: needsSecondaryAlpha ? alphaTranscodeData.buffer : null,
      webglFormat: webglFormat,
      mipLevels: mipLevels,
      hasAlpha: hasAlpha,
    }, transferList);
  }

  onmessage = (msg) => {
    // Each call to the worker must contain:
    let url = msg.data.url; // The URL of the basis image OR
    let buffer = msg.data.buffer; // An array buffer with the basis image data
    let allowSeparateAlpha = msg.data.allowSeparateAlpha;
    let supportedFormats = msg.data.supportedFormats; // The formats this device supports
    let id = msg.data.id; // A unique ID for the texture

    if (url) {
      // Make the call to fetch the basis texture data
      fetch(`../../${url}`).then(function(response) {
        if (response.ok) {
          response.arrayBuffer().then((arrayBuffer) => {
            if (BasisFile) {
              transcode(id, arrayBuffer, supportedFormats, allowSeparateAlpha);
            } else {
              BASIS_INITIALIZED.then(() => {
                transcode(id, arrayBuffer, supportedFormats, allowSeparateAlpha);
              });
            }
          });
        } else {
          fail(id, `Fetch failed: ${response.status}, ${response.statusText}`);
        }
      });
    } else if (buffer) {
      if (BasisFile) {
        transcode(id, buffer, supportedFormats, allowSeparateAlpha);
      } else {
        BASIS_INITIALIZED.then(() => {
          transcode(id, buffer, supportedFormats, allowSeparateAlpha);
        });
      }
    } else {
      fail(id, `No url or buffer specified`);
    }
  };
}