update(maxWidth, maxHeight, margins) {
    const {beginAtZero, grace, ticks: tickOpts} = this.options;
    const sampleSize = tickOpts.sampleSize;

    // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
    this.beforeUpdate();

    // Absorb the master measurements
    this.maxWidth = maxWidth;
    this.maxHeight = maxHeight;
    this._margins = margins = Object.assign({
      left: 0,
      right: 0,
      top: 0,
      bottom: 0
    }, margins);

    this.ticks = null;
    this._labelSizes = null;
    this._gridLineItems = null;
    this._labelItems = null;

    // Dimensions
    this.beforeSetDimensions();
    this.setDimensions();
    this.afterSetDimensions();

    this._maxLength = this.isHorizontal()
      ? this.width + margins.left + margins.right
      : this.height + margins.top + margins.bottom;

    // Data min/max
    if (!this._dataLimitsCached) {
      this.beforeDataLimits();
      this.determineDataLimits();
      this.afterDataLimits();
      this._range = _addGrace(this, grace, beginAtZero);
      this._dataLimitsCached = true;
    }

    this.beforeBuildTicks();

    this.ticks = this.buildTicks() || [];

    // Allow modification of ticks in callback.
    this.afterBuildTicks();

    // Compute tick rotation and fit using a sampled subset of labels
    // We generally don't need to compute the size of every single label for determining scale size
    const samplingEnabled = sampleSize < this.ticks.length;
    this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks);

    // configure is called twice, once here, once from core.controller.updateLayout.
    // Here we haven't been positioned yet, but dimensions are correct.
    // Variables set in configure are needed for calculateLabelRotation, and
    // it's ok that coordinates are not correct there, only dimensions matter.
    this.configure();

    // Tick Rotation
    this.beforeCalculateLabelRotation();
    this.calculateLabelRotation(); // Preconditions: number of ticks and sizes of largest labels must be calculated beforehand
    this.afterCalculateLabelRotation();

    // Auto-skip
    if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) {
      this.ticks = autoSkip(this, this.ticks);
      this._labelSizes = null;
      this.afterAutoSkip();
    }

    if (samplingEnabled) {
      // Generate labels using all non-skipped ticks
      this._convertTicksToLabels(this.ticks);
    }

    this.beforeFit();
    this.fit(); // Preconditions: label rotation and label sizes must be calculated beforehand
    this.afterFit();

    // IMPORTANT: after this point, we consider that `this.ticks` will NEVER change!

    this.afterUpdate();
  }
@param {number} maxWidth - the max width in pixels
@param {number} maxHeight - the max height in pixels
@param {{top: number, left: number, bottom: number, right: number}} margins - the space between the edge of the other scales and edge of the chart
  This space comes from two sources:
    - padding - space that's required to show the labels at the edges of the scale
    - thickness of scales or legends in another orientation