// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/** @type {number} */
const maxRange = 20;
/** @type {string} */
const defaultUnit = 'px';
/** @type {number} */
const sliderThumbRadius = 6;
/** @type {number} */
const canvasSize = 88;

/**
 * @unrestricted
 */
export class CSSShadowEditor extends UI.VBox {
  constructor() {
    super(true);
    this.registerRequiredCSS('inline_editor/cssShadowEditor.css');
    this.contentElement.tabIndex = 0;
    this.setDefaultFocusedElement(this.contentElement);

    this._typeField = this.contentElement.createChild('div', 'shadow-editor-field shadow-editor-flex-field');
    this._typeField.createChild('label', 'shadow-editor-label').textContent = Common.UIString('Type');
    this._outsetButton = this._typeField.createChild('button', 'shadow-editor-button-left');
    this._outsetButton.textContent = Common.UIString('Outset');
    this._outsetButton.addEventListener('click', this._onButtonClick.bind(this), false);
    this._insetButton = this._typeField.createChild('button', 'shadow-editor-button-right');
    this._insetButton.textContent = Common.UIString('Inset');
    this._insetButton.addEventListener('click', this._onButtonClick.bind(this), false);

    const xField = this.contentElement.createChild('div', 'shadow-editor-field');
    this._xInput = this._createTextInput(xField, Common.UIString('X offset'));
    const yField = this.contentElement.createChild('div', 'shadow-editor-field');
    this._yInput = this._createTextInput(yField, Common.UIString('Y offset'));
    this._xySlider = xField.createChild('canvas', 'shadow-editor-2D-slider');
    this._xySlider.width = canvasSize;
    this._xySlider.height = canvasSize;
    this._xySlider.tabIndex = -1;
    this._halfCanvasSize = canvasSize / 2;
    this._innerCanvasSize = this._halfCanvasSize - sliderThumbRadius;
    UI.installDragHandle(this._xySlider, this._dragStart.bind(this), this._dragMove.bind(this), null, 'default');
    this._xySlider.addEventListener('keydown', this._onCanvasArrowKey.bind(this), false);
    this._xySlider.addEventListener('blur', this._onCanvasBlur.bind(this), false);

    const blurField =
        this.contentElement.createChild('div', 'shadow-editor-field shadow-editor-flex-field shadow-editor-blur-field');
    this._blurInput = this._createTextInput(blurField, Common.UIString('Blur'));
    this._blurSlider = this._createSlider(blurField);

    this._spreadField = this.contentElement.createChild('div', 'shadow-editor-field shadow-editor-flex-field');
    this._spreadInput = this._createTextInput(this._spreadField, Common.UIString('Spread'));
    this._spreadSlider = this._createSlider(this._spreadField);
  }

  /**
   * @param {!Element} field
   * @param {string} propertyName
   * @return {!Element}
   */
  _createTextInput(field, propertyName) {
    const label = field.createChild('label', 'shadow-editor-label');
    label.textContent = propertyName;
    label.setAttribute('for', propertyName);
    const textInput = UI.createInput('shadow-editor-text-input', 'text');
    field.appendChild(textInput);
    textInput.id = propertyName;
    textInput.addEventListener('keydown', this._handleValueModification.bind(this), false);
    textInput.addEventListener('mousewheel', this._handleValueModification.bind(this), false);
    textInput.addEventListener('input', this._onTextInput.bind(this), false);
    textInput.addEventListener('blur', this._onTextBlur.bind(this), false);
    return textInput;
  }

  /**
   * @param {!Element} field
   * @return {!Element}
   */
  _createSlider(field) {
    const slider = UI.createSlider(0, maxRange, -1);
    slider.addEventListener('input', this._onSliderInput.bind(this), false);
    field.appendChild(slider);
    return slider;
  }

  /**
   * @override
   */
  wasShown() {
    this._updateUI();
  }

  /**
   * @param {!InlineEditor.CSSShadowModel} model
   */
  setModel(model) {
    this._model = model;
    this._typeField.classList.toggle('hidden', !model.isBoxShadow());
    this._spreadField.classList.toggle('hidden', !model.isBoxShadow());
    this._updateUI();
  }

  _updateUI() {
    this._updateButtons();
    this._xInput.value = this._model.offsetX().asCSSText();
    this._yInput.value = this._model.offsetY().asCSSText();
    this._blurInput.value = this._model.blurRadius().asCSSText();
    this._spreadInput.value = this._model.spreadRadius().asCSSText();
    this._blurSlider.value = this._model.blurRadius().amount;
    this._spreadSlider.value = this._model.spreadRadius().amount;
    this._updateCanvas(false);
  }

  _updateButtons() {
    this._insetButton.classList.toggle('enabled', this._model.inset());
    this._outsetButton.classList.toggle('enabled', !this._model.inset());
  }

  /**
   * @param {boolean} drawFocus
   */
  _updateCanvas(drawFocus) {
    const context = this._xySlider.getContext('2d');
    context.clearRect(0, 0, this._xySlider.width, this._xySlider.height);

    // Draw dashed axes.
    context.save();
    context.setLineDash([1, 1]);
    context.strokeStyle = 'rgba(210, 210, 210, 0.8)';
    context.beginPath();
    context.moveTo(this._halfCanvasSize, 0);
    context.lineTo(this._halfCanvasSize, canvasSize);
    context.moveTo(0, this._halfCanvasSize);
    context.lineTo(canvasSize, this._halfCanvasSize);
    context.stroke();
    context.restore();

    const thumbPoint = this._sliderThumbPosition();
    // Draw 2D slider line.
    context.save();
    context.translate(this._halfCanvasSize, this._halfCanvasSize);
    context.lineWidth = 2;
    context.strokeStyle = 'rgba(130, 130, 130, 0.75)';
    context.beginPath();
    context.moveTo(0, 0);
    context.lineTo(thumbPoint.x, thumbPoint.y);
    context.stroke();
    // Draw 2D slider thumb.
    if (drawFocus) {
      context.beginPath();
      context.fillStyle = 'rgba(66, 133, 244, 0.4)';
      context.arc(thumbPoint.x, thumbPoint.y, sliderThumbRadius + 2, 0, 2 * Math.PI);
      context.fill();
    }
    context.beginPath();
    context.fillStyle = '#4285F4';
    context.arc(thumbPoint.x, thumbPoint.y, sliderThumbRadius, 0, 2 * Math.PI);
    context.fill();
    context.restore();
  }

  /**
   * @param {!Event} event
   */
  _onButtonClick(event) {
    const insetClicked = (event.currentTarget === this._insetButton);
    if (insetClicked && this._model.inset() || !insetClicked && !this._model.inset()) {
      return;
    }
    this._model.setInset(insetClicked);
    this._updateButtons();
    this.dispatchEventToListeners(Events.ShadowChanged, this._model);
  }

  /**
   * @param {!Event} event
   */
  _handleValueModification(event) {
    const modifiedValue = UI.createReplacementString(event.currentTarget.value, event, customNumberHandler);
    if (!modifiedValue) {
      return;
    }
    const length = InlineEditor.CSSLength.parse(modifiedValue);
    if (!length) {
      return;
    }
    if (event.currentTarget === this._blurInput && length.amount < 0) {
      length.amount = 0;
    }
    event.currentTarget.value = length.asCSSText();
    event.currentTarget.selectionStart = 0;
    event.currentTarget.selectionEnd = event.currentTarget.value.length;
    this._onTextInput(event);
    event.consume(true);

    /**
     * @param {string} prefix
     * @param {number} number
     * @param {string} suffix
     * @return {string}
     */
    function customNumberHandler(prefix, number, suffix) {
      if (!suffix.length) {
        suffix = defaultUnit;
      }
      return prefix + number + suffix;
    }
  }

  /**
   * @param {!Event} event
   */
  _onTextInput(event) {
    this._changedElement = event.currentTarget;
    this._changedElement.classList.remove('invalid');
    const length = InlineEditor.CSSLength.parse(event.currentTarget.value);
    if (!length || event.currentTarget === this._blurInput && length.amount < 0) {
      return;
    }
    if (event.currentTarget === this._xInput) {
      this._model.setOffsetX(length);
      this._updateCanvas(false);
    } else if (event.currentTarget === this._yInput) {
      this._model.setOffsetY(length);
      this._updateCanvas(false);
    } else if (event.currentTarget === this._blurInput) {
      this._model.setBlurRadius(length);
      this._blurSlider.value = length.amount;
    } else if (event.currentTarget === this._spreadInput) {
      this._model.setSpreadRadius(length);
      this._spreadSlider.value = length.amount;
    }
    this.dispatchEventToListeners(Events.ShadowChanged, this._model);
  }

  _onTextBlur() {
    if (!this._changedElement) {
      return;
    }
    let length = !this._changedElement.value.trim() ? InlineEditor.CSSLength.zero() :
                                                      InlineEditor.CSSLength.parse(this._changedElement.value);
    if (!length) {
      length = InlineEditor.CSSLength.parse(this._changedElement.value + defaultUnit);
    }
    if (!length) {
      this._changedElement.classList.add('invalid');
      this._changedElement = null;
      return;
    }
    if (this._changedElement === this._xInput) {
      this._model.setOffsetX(length);
      this._xInput.value = length.asCSSText();
      this._updateCanvas(false);
    } else if (this._changedElement === this._yInput) {
      this._model.setOffsetY(length);
      this._yInput.value = length.asCSSText();
      this._updateCanvas(false);
    } else if (this._changedElement === this._blurInput) {
      if (length.amount < 0) {
        length = InlineEditor.CSSLength.zero();
      }
      this._model.setBlurRadius(length);
      this._blurInput.value = length.asCSSText();
      this._blurSlider.value = length.amount;
    } else if (this._changedElement === this._spreadInput) {
      this._model.setSpreadRadius(length);
      this._spreadInput.value = length.asCSSText();
      this._spreadSlider.value = length.amount;
    }
    this._changedElement = null;
    this.dispatchEventToListeners(Events.ShadowChanged, this._model);
  }

  /**
   * @param {!Event} event
   */
  _onSliderInput(event) {
    if (event.currentTarget === this._blurSlider) {
      this._model.setBlurRadius(
          new InlineEditor.CSSLength(this._blurSlider.value, this._model.blurRadius().unit || defaultUnit));
      this._blurInput.value = this._model.blurRadius().asCSSText();
      this._blurInput.classList.remove('invalid');
    } else if (event.currentTarget === this._spreadSlider) {
      this._model.setSpreadRadius(
          new InlineEditor.CSSLength(this._spreadSlider.value, this._model.spreadRadius().unit || defaultUnit));
      this._spreadInput.value = this._model.spreadRadius().asCSSText();
      this._spreadInput.classList.remove('invalid');
    }
    this.dispatchEventToListeners(Events.ShadowChanged, this._model);
  }

  /**
   * @param {!MouseEvent} event
   * @return {boolean}
   */
  _dragStart(event) {
    this._xySlider.focus();
    this._updateCanvas(true);
    this._canvasOrigin = new UI.Geometry.Point(
        this._xySlider.totalOffsetLeft() + this._halfCanvasSize,
        this._xySlider.totalOffsetTop() + this._halfCanvasSize);
    const clickedPoint = new UI.Geometry.Point(event.x - this._canvasOrigin.x, event.y - this._canvasOrigin.y);
    const thumbPoint = this._sliderThumbPosition();
    if (clickedPoint.distanceTo(thumbPoint) >= sliderThumbRadius) {
      this._dragMove(event);
    }
    return true;
  }

  /**
   * @param {!MouseEvent} event
   */
  _dragMove(event) {
    let point = new UI.Geometry.Point(event.x - this._canvasOrigin.x, event.y - this._canvasOrigin.y);
    if (event.shiftKey) {
      point = this._snapToClosestDirection(point);
    }
    const constrainedPoint = this._constrainPoint(point, this._innerCanvasSize);
    const newX = Math.round((constrainedPoint.x / this._innerCanvasSize) * maxRange);
    const newY = Math.round((constrainedPoint.y / this._innerCanvasSize) * maxRange);

    if (event.shiftKey) {
      this._model.setOffsetX(new InlineEditor.CSSLength(newX, this._model.offsetX().unit || defaultUnit));
      this._model.setOffsetY(new InlineEditor.CSSLength(newY, this._model.offsetY().unit || defaultUnit));
    } else {
      if (!event.altKey) {
        this._model.setOffsetX(new InlineEditor.CSSLength(newX, this._model.offsetX().unit || defaultUnit));
      }
      if (!UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) {
        this._model.setOffsetY(new InlineEditor.CSSLength(newY, this._model.offsetY().unit || defaultUnit));
      }
    }
    this._xInput.value = this._model.offsetX().asCSSText();
    this._yInput.value = this._model.offsetY().asCSSText();
    this._xInput.classList.remove('invalid');
    this._yInput.classList.remove('invalid');
    this._updateCanvas(true);
    this.dispatchEventToListeners(Events.ShadowChanged, this._model);
  }

  _onCanvasBlur() {
    this._updateCanvas(false);
  }

  /**
   * @param {!Event} event
   */
  _onCanvasArrowKey(event) {
    let shiftX = 0;
    let shiftY = 0;
    if (event.key === 'ArrowRight') {
      shiftX = 1;
    } else if (event.key === 'ArrowLeft') {
      shiftX = -1;
    } else if (event.key === 'ArrowUp') {
      shiftY = -1;
    } else if (event.key === 'ArrowDown') {
      shiftY = 1;
    }

    if (!shiftX && !shiftY) {
      return;
    }
    event.consume(true);

    if (shiftX) {
      const offsetX = this._model.offsetX();
      const newAmount = Number.constrain(offsetX.amount + shiftX, -maxRange, maxRange);
      if (newAmount === offsetX.amount) {
        return;
      }
      this._model.setOffsetX(new InlineEditor.CSSLength(newAmount, offsetX.unit || defaultUnit));
      this._xInput.value = this._model.offsetX().asCSSText();
      this._xInput.classList.remove('invalid');
    }
    if (shiftY) {
      const offsetY = this._model.offsetY();
      const newAmount = Number.constrain(offsetY.amount + shiftY, -maxRange, maxRange);
      if (newAmount === offsetY.amount) {
        return;
      }
      this._model.setOffsetY(new InlineEditor.CSSLength(newAmount, offsetY.unit || defaultUnit));
      this._yInput.value = this._model.offsetY().asCSSText();
      this._yInput.classList.remove('invalid');
    }
    this._updateCanvas(true);
    this.dispatchEventToListeners(Events.ShadowChanged, this._model);
  }

  /**
   * @param {!UI.Geometry.Point} point
   * @param {number} max
   * @return {!UI.Geometry.Point}
   */
  _constrainPoint(point, max) {
    if (Math.abs(point.x) <= max && Math.abs(point.y) <= max) {
      return new UI.Geometry.Point(point.x, point.y);
    }
    return point.scale(max / Math.max(Math.abs(point.x), Math.abs(point.y)));
  }

  /**
   * @param {!UI.Geometry.Point} point
   * @return {!UI.Geometry.Point}
   */
  _snapToClosestDirection(point) {
    let minDistance = Number.MAX_VALUE;
    let closestPoint = point;

    const directions = [
      new UI.Geometry.Point(0, -1),  // North
      new UI.Geometry.Point(1, -1),  // Northeast
      new UI.Geometry.Point(1, 0),   // East
      new UI.Geometry.Point(1, 1)    // Southeast
    ];

    for (const direction of directions) {
      const projection = point.projectOn(direction);
      const distance = point.distanceTo(projection);
      if (distance < minDistance) {
        minDistance = distance;
        closestPoint = projection;
      }
    }

    return closestPoint;
  }

  /**
   * @return {!UI.Geometry.Point}
   */
  _sliderThumbPosition() {
    const x = (this._model.offsetX().amount / maxRange) * this._innerCanvasSize;
    const y = (this._model.offsetY().amount / maxRange) * this._innerCanvasSize;
    return this._constrainPoint(new UI.Geometry.Point(x, y), this._innerCanvasSize);
  }
}

/** @enum {symbol} */
export const Events = {
  ShadowChanged: Symbol('ShadowChanged')
};

/* Legacy exported object */
self.InlineEditor = self.InlineEditor || {};

/* Legacy exported object */
InlineEditor = InlineEditor || {};

/** @constructor */
InlineEditor.CSSShadowEditor = CSSShadowEditor;

InlineEditor.CSSShadowEditor.Events = Events;
