/*
 * 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;
          needsSecondaryAlpha = true;
        } 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`);
    }
  };
}