/* eslint-disable complexity */
import GL from '../constants';
import { Buffer } from '../webgl';
export default class Attribute {
  constructor(gl, opts = {}) {
    const _opts$id = opts.id,
          id = _opts$id === void 0 ? 'unnamed-attribute' : _opts$id,
          type = opts.type,
          _opts$isIndexed = opts.isIndexed,
          isIndexed = _opts$isIndexed === void 0 ? false : _opts$isIndexed; // Options that cannot be changed later

    this.gl = gl;
    this.id = id;
    this.isIndexed = isIndexed;
    this.target = isIndexed ? GL.ELEMENT_ARRAY_BUFFER : GL.ARRAY_BUFFER;
    this.type = type; // Initialize the attribute descriptor, with WebGL and metadata fields

    this.value = null;
    this.externalBuffer = null;
    this.buffer = null;
    this.userData = {}; // Reserved for application

    this.update(opts); // Sanity - no app fields on our attributes. Use userData instead.

    Object.seal(this); // Check all fields and generate helpful error messages

    this._validateAttributeDefinition();
  }

  delete() {
    if (this.buffer) {
      this.buffer.delete();
      this.buffer = null;
    }
  }

  update(opts) {
    const value = opts.value,
          buffer = opts.buffer,
          _opts$size = opts.size,
          size = _opts$size === void 0 ? this.size : _opts$size,
          _opts$offset = opts.offset,
          offset = _opts$offset === void 0 ? this.offset || 0 : _opts$offset,
          _opts$stride = opts.stride,
          stride = _opts$stride === void 0 ? this.stride || 0 : _opts$stride,
          _opts$normalized = opts.normalized,
          normalized = _opts$normalized === void 0 ? this.normalized || false : _opts$normalized,
          _opts$integer = opts.integer,
          integer = _opts$integer === void 0 ? this.integer || false : _opts$integer,
          _opts$instanced = opts.instanced,
          instanced = _opts$instanced === void 0 ? this.instanced || 0 : _opts$instanced,
          _opts$constant = opts.constant,
          constant = _opts$constant === void 0 ? this.constant || false : _opts$constant,
          isInstanced = opts.isInstanced;
    this.size = size;
    this.offset = offset;
    this.stride = stride;
    this.normalized = normalized;
    this.integer = integer;
    this.constant = constant;

    if (isInstanced !== undefined) {
      this.instanced = isInstanced ? 1 : 0;
    } else {
      this.instanced = instanced;
    }

    if (buffer) {
      this.externalBuffer = buffer;
      this.constant = false;
      this.type = buffer.accessor.type;

      if (buffer.accessor.divisor !== undefined) {
        this.instanced = buffer.accessor.divisor > 0;
      }
    } else if (value) {
      this.externalBuffer = null;
      this.value = value;

      if (!constant) {
        // Create buffer if needed
        this.buffer = this.buffer || new Buffer(this.gl, Object.assign({}, opts, {
          target: this.target,
          type: this.type
        }));
        this.buffer.setData({
          data: value
        });
        this.type = this.buffer.accessor.type;
      }
    }
  }

  getBuffer() {
    if (this.constant) {
      return null;
    }

    return this.externalBuffer || this.buffer;
  }

  getValue() {
    if (this.constant) {
      return this.value;
    }

    const buffer = this.externalBuffer || this.buffer;

    if (buffer) {
      return [buffer, this];
    }

    return null;
  }

  _validateAttributeDefinition() {// Can be undefined for buffers (auto deduced from shaders)
    // or larger than 4 for uniform arrays
    // assert(
    //   this.size >= 1 && this.size <= 4,
    //   `Attribute definition for ${this.id} invalid size`
    // );
  }

}
//# sourceMappingURL=attribute.js.map