import { m as macro } from '../../macros2.js';
import vtkDataArray from '../../Common/Core/DataArray.js';
import vtkWebGPUTexture from './Texture.js';

const {
  VtkDataTypes
} = vtkDataArray;

// ----------------------------------------------------------------------------
// Global methods
// ----------------------------------------------------------------------------

// ----------------------------------------------------------------------------
// vtkWebGPUTextureManager methods
// ----------------------------------------------------------------------------

function vtkWebGPUTextureManager(publicAPI, model) {
  // Set our className
  model.classHierarchy.push('vtkWebGPUTextureManager');

  // fills in request values based on what is missing/provided
  function _fillRequest(req) {
    // fill in values based on imageData if the request has it
    if (req.imageData) {
      req.dataArray = req.imageData.getPointData().getScalars();
      req.time = req.dataArray.getMTime();
      req.nativeArray = req.dataArray.getData();
      const dims = req.imageData.getDimensions();
      req.width = dims[0];
      req.height = dims[1];
      req.depth = dims[2];
      const numComp = req.dataArray.getNumberOfComponents();
      // todo fix handling of 3 component
      switch (numComp) {
        case 1:
          req.format = 'r';
          break;
        case 2:
          req.format = 'rg';
          break;
        case 3:
        case 4:
        default:
          req.format = 'rgba';
          break;
      }
      const dataType = req.dataArray.getDataType();
      switch (dataType) {
        case VtkDataTypes.UNSIGNED_CHAR:
          req.format += '8unorm';
          break;
        // todo extend to other types that are not filterable
        // as they can be useful
        case VtkDataTypes.FLOAT:
        case VtkDataTypes.UNSIGNED_INT:
        case VtkDataTypes.INT:
        case VtkDataTypes.DOUBLE:
        case VtkDataTypes.UNSIGNED_SHORT:
        case VtkDataTypes.SHORT:
        default:
          req.format += '16float';
          break;
      }
    }

    // fill in values based on image if the request has it
    if (req.image) {
      req.width = req.image.width;
      req.height = req.image.height;
      req.depth = 1;
      req.format = 'rgba8unorm';
    }

    // fill in based on js imageData
    if (req.jsImageData) {
      req.width = req.jsImageData.width;
      req.height = req.jsImageData.height;
      req.depth = 1;
      req.format = 'rgba8unorm';
      req.flip = true;
      req.nativeArray = req.jsImageData.data;
    }
    if (req.canvas) {
      req.width = req.canvas.width;
      req.height = req.canvas.height;
      req.depth = 1;
      req.format = 'rgba8unorm';
      req.flip = true;
      /* eslint-disable no-undef */
      /* eslint-disable no-bitwise */
      req.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;
      /* eslint-enable no-undef */
      /* eslint-enable no-bitwise */
    }
  }

  // create a texture (used by getTexture)
  function _createTexture(req) {
    const newTex = vtkWebGPUTexture.newInstance();
    newTex.create(model.device, {
      width: req.width,
      height: req.height,
      depth: req.depth,
      format: req.format,
      usage: req.usage,
      mipLevel: req.mipLevel
    });

    // fill the texture if we have data
    if (req.nativeArray || req.image || req.canvas) {
      newTex.writeImageData(req);
    }
    return newTex;
  }

  // get a texture or create it if not cached.
  // this is the main entry point
  publicAPI.getTexture = req => {
    // if we have a source the get/create/cache the texture
    if (req.hash) {
      // if a matching texture already exists then return it
      return model.device.getCachedObject(req.hash, _createTexture, req);
    }
    return _createTexture(req);
  };
  publicAPI.getTextureForImageData = imgData => {
    const treq = {
      time: imgData.getMTime()
    };
    treq.imageData = imgData;
    // fill out the req time and format based on imageData/image
    _fillRequest(treq);
    treq.hash = treq.time + treq.format + treq.mipLevel;
    return model.device.getTextureManager().getTexture(treq);
  };
  publicAPI.getTextureForVTKTexture = srcTexture => {
    const treq = {
      time: srcTexture.getMTime()
    };
    if (srcTexture.getInputData()) {
      treq.imageData = srcTexture.getInputData();
    } else if (srcTexture.getImage()) {
      treq.image = srcTexture.getImage();
    } else if (srcTexture.getJsImageData()) {
      treq.jsImageData = srcTexture.getJsImageData();
    } else if (srcTexture.getCanvas()) {
      treq.canvas = srcTexture.getCanvas();
    }
    // fill out the req time and format based on imageData/image
    _fillRequest(treq);
    treq.mipLevel = srcTexture.getMipLevel();
    treq.hash = treq.time + treq.format + treq.mipLevel;
    return model.device.getTextureManager().getTexture(treq);
  };
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
  handle: null,
  device: null
};

// ----------------------------------------------------------------------------

function extend(publicAPI, model) {
  let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  Object.assign(model, DEFAULT_VALUES, initialValues);

  // Object methods
  macro.obj(publicAPI, model);
  macro.setGet(publicAPI, model, ['device']);
  vtkWebGPUTextureManager(publicAPI, model);
}

// ----------------------------------------------------------------------------

const newInstance = macro.newInstance(extend);

// ----------------------------------------------------------------------------

var vtkWebGPUTextureManager$1 = {
  newInstance,
  extend
};

export { vtkWebGPUTextureManager$1 as default, extend, newInstance };
