import Viewport from '../viewports/viewport';
import { parsePosition, getPosition } from '../utils/positions';
import { deepEqual } from '../utils/deep-equal';
import assert from '../utils/assert';

export default class View {
  constructor(props = {}) {
    var _props$id = props.id;
    const id = _props$id === undefined ? null : _props$id;
    var _props$x = props.x;
    const x = _props$x === undefined ? 0 : _props$x;
    var _props$y = props.y;
    const y = _props$y === undefined ? 0 : _props$y;
    var _props$width = props.width;
    const width = _props$width === undefined ? '100%' : _props$width;
    var _props$height = props.height;
    const height = _props$height === undefined ? '100%' : _props$height;
    var _props$type = props.type;
    const type = _props$type === undefined ? Viewport : _props$type;
    var _props$projectionMatr = props.projectionMatrix;
    const projectionMatrix = _props$projectionMatr === undefined ? null : _props$projectionMatr;
    var _props$fovy = props.fovy;
    const fovy = _props$fovy === undefined ? 75 : _props$fovy;
    var _props$near = props.near;
    const near = _props$near === undefined ? 0.1 : _props$near;
    var _props$far = props.far;
    const far = _props$far === undefined ? 1000 : _props$far;
    var _props$modelMatrix = props.modelMatrix;
    const modelMatrix = _props$modelMatrix === undefined ? null : _props$modelMatrix;
    var _props$viewportInstan = props.viewportInstance;
    const viewportInstance = _props$viewportInstan === undefined ? null : _props$viewportInstan;


    assert(!viewportInstance || viewportInstance instanceof Viewport);
    this.viewportInstance = viewportInstance;

    // Id
    this.id = id || this.constructor.displayName || 'view';
    this.type = type;

    this.props = Object.assign({}, props, {
      projectionMatrix,
      fovy,
      near,
      far,
      modelMatrix
    });

    // Extents
    this._parseDimensions({ x, y, width, height });

    // Bind methods for easy access
    this.equals = this.equals.bind(this);

    Object.seal(this);
  }

  equals(view) {
    if (this === view) {
      return true;
    }

    // if `viewportInstance` is set, it is the only prop that is used
    // Delegate to `Viewport.equals`
    if (this.viewportInstance) {
      return view.viewportInstance && this.viewportInstance.equals(view.viewportInstance);
    }

    // TODO - implement deep equal on view descriptors
    const viewChanged = deepEqual(this, view);

    return viewChanged;
  }

  // Build a `Viewport` from a view descriptor
  // TODO - add support for autosizing viewports using width and height
  makeViewport({ width, height, viewState }) {
    if (this.viewportInstance) {
      return this.viewportInstance;
    }

    // Resolve relative viewport dimensions
    const viewportDimensions = this.getDimensions({ width, height });
    const props = Object.assign({ viewState }, viewState, this.props, viewportDimensions);
    return this._getViewport(props);
  }

  // Resolve relative viewport dimensions into actual dimensions (y='50%', width=800 => y=400)
  getDimensions({ width, height }) {
    return {
      x: getPosition(this._x, width),
      y: getPosition(this._y, height),
      width: getPosition(this._width, width),
      height: getPosition(this._height, height)
    };
  }

  // Overridable method
  _getViewport(props) {
    // Get the type of the viewport
    const ViewportType = this.type;

    return new ViewportType(props);
  }

  // Parse relative viewport dimension descriptors (e.g {y: '50%', height: '50%'})
  _parseDimensions({ x, y, width, height }) {
    this._x = parsePosition(x);
    this._y = parsePosition(y);
    this._width = parsePosition(width);
    this._height = parsePosition(height);
  }
}
//# sourceMappingURL=view.js.map