// Copyright (c) 2015 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.
/**
 * @unrestricted
 */
Emulation.SensorsView = class extends UI.VBox {
  constructor() {
    super(true);
    this.registerRequiredCSS('emulation/sensors.css');
    this.contentElement.classList.add('sensors-view');

    this._geolocationSetting = Common.settings.createSetting('emulation.geolocationOverride', '');
    this._geolocation = SDK.EmulationModel.Geolocation.parseSetting(this._geolocationSetting.get());
    this._geolocationOverrideEnabled = false;
    this._createGeolocationSection(this._geolocation);

    this.contentElement.createChild('div').classList.add('panel-section-separator');

    this._deviceOrientationSetting = Common.settings.createSetting('emulation.deviceOrientationOverride', '');
    this._deviceOrientation = SDK.EmulationModel.DeviceOrientation.parseSetting(this._deviceOrientationSetting.get());
    this._deviceOrientationOverrideEnabled = false;
    this._createDeviceOrientationSection();

    this.contentElement.createChild('div').classList.add('panel-section-separator');

    this._appendTouchControl();
  }

  /**
   * @return {!Emulation.SensorsView}
   */
  static instance() {
    if (!Emulation.SensorsView._instanceObject)
      Emulation.SensorsView._instanceObject = new Emulation.SensorsView();
    return Emulation.SensorsView._instanceObject;
  }

  /**
   * @param {!SDK.EmulationModel.Geolocation} geolocation
   */
  _createGeolocationSection(geolocation) {
    const geogroup = this.contentElement.createChild('section', 'sensors-group');
    geogroup.createChild('div', 'sensors-group-title').textContent = Common.UIString('Geolocation');
    const fields = geogroup.createChild('div', 'geo-fields');

    const noOverrideOption = {
      title: Common.UIString('No override'),
      location: Emulation.SensorsView.NonPresetOptions.NoOverride
    };
    const customLocationOption = {
      title: Common.UIString('Custom location...'),
      location: Emulation.SensorsView.NonPresetOptions.Custom
    };
    this._locationSelectElement = this.contentElement.createChild('select', 'chrome-select');
    this._locationSelectElement.appendChild(new Option(noOverrideOption.title, noOverrideOption.location));
    this._locationSelectElement.appendChild(new Option(customLocationOption.title, customLocationOption.location));

    const locationGroups = Emulation.SensorsView.PresetLocations;
    for (let i = 0; i < locationGroups.length; ++i) {
      const group = locationGroups[i].value;
      const groupElement = this._locationSelectElement.createChild('optgroup');
      groupElement.label = locationGroups[i].title;
      for (let j = 0; j < group.length; ++j)
        groupElement.appendChild(new Option(group[j].title, group[j].location));
    }
    this._locationSelectElement.selectedIndex = 0;
    fields.appendChild(this._locationSelectElement);
    this._locationSelectElement.addEventListener('change', this._geolocationSelectChanged.bind(this));

    // Validated input fieldset.
    this._fieldsetElement = fields.createChild('fieldset');
    this._fieldsetElement.disabled = !this._geolocationOverrideEnabled;
    this._fieldsetElement.id = 'geolocation-override-section';

    const latitudeGroup = this._fieldsetElement.createChild('div', 'latlong-group');
    const longitudeGroup = this._fieldsetElement.createChild('div', 'latlong-group');

    this._latitudeInput = UI.createInput('', 'number');
    latitudeGroup.appendChild(this._latitudeInput);
    this._latitudeInput.setAttribute('step', 'any');
    this._latitudeInput.value = 0;
    this._latitudeSetter = UI.bindInput(
        this._latitudeInput, this._applyGeolocationUserInput.bind(this),
        SDK.EmulationModel.Geolocation.latitudeValidator, true, 0.1);
    this._latitudeSetter(String(geolocation.latitude));

    this._longitudeInput = UI.createInput('', 'number');
    longitudeGroup.appendChild(this._longitudeInput);
    this._longitudeInput.setAttribute('step', 'any');
    this._longitudeInput.value = 0;
    this._longitudeSetter = UI.bindInput(
        this._longitudeInput, this._applyGeolocationUserInput.bind(this),
        SDK.EmulationModel.Geolocation.longitudeValidator, true, 0.1);
    this._longitudeSetter(String(geolocation.longitude));

    const cmdOrCtrl = Host.isMac() ? '\u2318' : 'Ctrl';
    const modifierKeyMessage = ls`Adjust with mousewheel or up/down keys. ${cmdOrCtrl}: ±10, Shift: ±1, Alt: ±0.01`;
    this._latitudeInput.title = modifierKeyMessage;
    this._longitudeInput.title = modifierKeyMessage;

    latitudeGroup.createChild('div', 'latlong-title').textContent = Common.UIString('Latitude');
    longitudeGroup.createChild('div', 'latlong-title').textContent = Common.UIString('Longitude');
  }

  _geolocationSelectChanged() {
    this._fieldsetElement.disabled = false;
    const value = this._locationSelectElement.options[this._locationSelectElement.selectedIndex].value;
    if (value === Emulation.SensorsView.NonPresetOptions.NoOverride) {
      this._geolocationOverrideEnabled = false;
      this._fieldsetElement.disabled = true;
    } else if (value === Emulation.SensorsView.NonPresetOptions.Custom) {
      this._geolocationOverrideEnabled = true;
    } else if (value === Emulation.SensorsView.NonPresetOptions.Unavailable) {
      this._geolocationOverrideEnabled = true;
      this._geolocation = new SDK.EmulationModel.Geolocation(0, 0, true);
    } else {
      this._geolocationOverrideEnabled = true;
      const coordinates = JSON.parse(value);
      this._geolocation = new SDK.EmulationModel.Geolocation(coordinates[0], coordinates[1], false);
      this._latitudeSetter(coordinates[0]);
      this._longitudeSetter(coordinates[1]);
    }

    this._applyGeolocation();
    if (value === Emulation.SensorsView.NonPresetOptions.Custom)
      this._latitudeInput.focus();
  }

  _applyGeolocationUserInput() {
    const geolocation = SDK.EmulationModel.Geolocation.parseUserInput(
        this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), '');
    if (!geolocation)
      return;

    this._setSelectElementLabel(this._locationSelectElement, Emulation.SensorsView.NonPresetOptions.Custom);
    this._geolocation = geolocation;
    this._applyGeolocation();
  }

  _applyGeolocation() {
    if (this._geolocationOverrideEnabled)
      this._geolocationSetting.set(this._geolocation.toSetting());
    for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
      emulationModel.emulateGeolocation(this._geolocationOverrideEnabled ? this._geolocation : null);
  }

  _createDeviceOrientationSection() {
    const orientationGroup = this.contentElement.createChild('section', 'sensors-group');
    orientationGroup.createChild('div', 'sensors-group-title').textContent = Common.UIString('Orientation');
    const orientationContent = orientationGroup.createChild('div', 'orientation-content');
    const fields = orientationContent.createChild('div', 'orientation-fields');

    const orientationOffOption = {
      title: Common.UIString('Off'),
      orientation: Emulation.SensorsView.NonPresetOptions.NoOverride
    };
    const customOrientationOption = {
      title: Common.UIString('Custom orientation...'),
      orientation: Emulation.SensorsView.NonPresetOptions.Custom
    };
    this._orientationSelectElement = this.contentElement.createChild('select', 'chrome-select');
    this._orientationSelectElement.appendChild(
        new Option(orientationOffOption.title, orientationOffOption.orientation));
    this._orientationSelectElement.appendChild(
        new Option(customOrientationOption.title, customOrientationOption.orientation));

    const orientationGroups = Emulation.SensorsView.PresetOrientations;
    for (let i = 0; i < orientationGroups.length; ++i) {
      const groupElement = this._orientationSelectElement.createChild('optgroup');
      groupElement.label = orientationGroups[i].title;
      const group = orientationGroups[i].value;
      for (let j = 0; j < group.length; ++j)
        groupElement.appendChild(new Option(group[j].title, group[j].orientation));
    }
    this._orientationSelectElement.selectedIndex = 0;
    fields.appendChild(this._orientationSelectElement);
    this._orientationSelectElement.addEventListener('change', this._orientationSelectChanged.bind(this));

    this._deviceOrientationFieldset = this._createDeviceOrientationOverrideElement(this._deviceOrientation);

    this._stageElement = orientationContent.createChild('div', 'orientation-stage');
    this._stageElement.title = Common.UIString('Shift+drag horizontally to rotate around the y-axis');
    this._orientationLayer = this._stageElement.createChild('div', 'orientation-layer');
    this._boxElement = this._orientationLayer.createChild('section', 'orientation-box orientation-element');

    this._boxElement.createChild('section', 'orientation-front orientation-element');
    this._boxElement.createChild('section', 'orientation-top orientation-element');
    this._boxElement.createChild('section', 'orientation-back orientation-element');
    this._boxElement.createChild('section', 'orientation-left orientation-element');
    this._boxElement.createChild('section', 'orientation-right orientation-element');
    this._boxElement.createChild('section', 'orientation-bottom orientation-element');

    UI.installDragHandle(
        this._stageElement, this._onBoxDragStart.bind(this), this._onBoxDrag.bind(this), null, '-webkit-grabbing',
        '-webkit-grab');

    fields.appendChild(this._deviceOrientationFieldset);
    this._enableOrientationFields(true);
    this._setBoxOrientation(this._deviceOrientation, false);
  }

  /**
   * @param {?boolean} disable
   */
  _enableOrientationFields(disable) {
    if (disable) {
      this._deviceOrientationFieldset.disabled = true;
      this._stageElement.classList.add('disabled');
    } else {
      this._deviceOrientationFieldset.disabled = false;
      this._stageElement.classList.remove('disabled');
    }
  }

  _orientationSelectChanged() {
    const value = this._orientationSelectElement.options[this._orientationSelectElement.selectedIndex].value;
    this._enableOrientationFields(false);

    if (value === Emulation.SensorsView.NonPresetOptions.NoOverride) {
      this._deviceOrientationOverrideEnabled = false;
      this._enableOrientationFields(true);
    } else if (value === Emulation.SensorsView.NonPresetOptions.Custom) {
      this._deviceOrientationOverrideEnabled = true;
      this._alphaElement.focus();
    } else {
      const parsedValue = JSON.parse(value);
      this._deviceOrientationOverrideEnabled = true;
      this._deviceOrientation =
          new SDK.EmulationModel.DeviceOrientation(parsedValue[0], parsedValue[1], parsedValue[2]);
      this._setDeviceOrientation(
          this._deviceOrientation, Emulation.SensorsView.DeviceOrientationModificationSource.SelectPreset);
    }
  }

  _applyDeviceOrientation() {
    if (this._deviceOrientationOverrideEnabled)
      this._deviceOrientationSetting.set(this._deviceOrientation.toSetting());
    for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
      emulationModel.emulateDeviceOrientation(this._deviceOrientationOverrideEnabled ? this._deviceOrientation : null);
  }

  /**
   * @param {!Element} selectElement
   * @param {string} labelValue
   */
  _setSelectElementLabel(selectElement, labelValue) {
    const optionValues = Array.prototype.map.call(selectElement.options, x => x.value);
    selectElement.selectedIndex = optionValues.indexOf(labelValue);
  }

  _applyDeviceOrientationUserInput() {
    this._setDeviceOrientation(
        SDK.EmulationModel.DeviceOrientation.parseUserInput(
            this._alphaElement.value.trim(), this._betaElement.value.trim(), this._gammaElement.value.trim()),
        Emulation.SensorsView.DeviceOrientationModificationSource.UserInput);
    this._setSelectElementLabel(this._orientationSelectElement, Emulation.SensorsView.NonPresetOptions.Custom);
  }

  _resetDeviceOrientation() {
    this._setDeviceOrientation(
        new SDK.EmulationModel.DeviceOrientation(0, 90, 0),
        Emulation.SensorsView.DeviceOrientationModificationSource.ResetButton);
    this._setSelectElementLabel(this._orientationSelectElement, '[0, 90, 0]');
  }

  /**
   * @param {?SDK.EmulationModel.DeviceOrientation} deviceOrientation
   * @param {!Emulation.SensorsView.DeviceOrientationModificationSource} modificationSource
   */
  _setDeviceOrientation(deviceOrientation, modificationSource) {
    if (!deviceOrientation)
      return;

    /**
     * @param {number} angle
     * @return {number}
     */
    function roundAngle(angle) {
      return Math.round(angle * 10000) / 10000;
    }

    if (modificationSource !== Emulation.SensorsView.DeviceOrientationModificationSource.UserInput) {
      this._alphaSetter(roundAngle(deviceOrientation.alpha));
      this._betaSetter(roundAngle(deviceOrientation.beta));
      this._gammaSetter(roundAngle(deviceOrientation.gamma));
    }

    const animate = modificationSource !== Emulation.SensorsView.DeviceOrientationModificationSource.UserDrag;
    this._setBoxOrientation(deviceOrientation, animate);

    this._deviceOrientation = deviceOrientation;
    this._applyDeviceOrientation();
  }

  /**
   * @param {!Element} parentElement
   * @param {!Element} input
   * @param {string} label
   * @return {function(string)}
   */
  _createAxisInput(parentElement, input, label) {
    const div = parentElement.createChild('div', 'orientation-axis-input-container');
    div.appendChild(input);
    div.createTextChild(label);
    input.type = 'number';
    return UI.bindInput(
        input, this._applyDeviceOrientationUserInput.bind(this), SDK.EmulationModel.DeviceOrientation.validator, true);
  }

  /**
   * @param {!SDK.EmulationModel.DeviceOrientation} deviceOrientation
   * @return {!Element}
   */
  _createDeviceOrientationOverrideElement(deviceOrientation) {
    const fieldsetElement = createElement('fieldset');
    fieldsetElement.classList.add('device-orientation-override-section');
    const cellElement = fieldsetElement.createChild('td', 'orientation-inputs-cell');

    this._alphaElement = UI.createInput();
    this._alphaElement.setAttribute('step', 'any');
    this._alphaSetter = this._createAxisInput(cellElement, this._alphaElement, Common.UIString('\u03B1 (alpha)'));
    this._alphaSetter(String(deviceOrientation.alpha));

    this._betaElement = UI.createInput();
    this._betaElement.setAttribute('step', 'any');
    this._betaSetter = this._createAxisInput(cellElement, this._betaElement, Common.UIString('\u03B2 (beta)'));
    this._betaSetter(String(deviceOrientation.beta));

    this._gammaElement = UI.createInput();
    this._gammaElement.setAttribute('step', 'any');
    this._gammaSetter = this._createAxisInput(cellElement, this._gammaElement, Common.UIString('\u03B3 (gamma)'));
    this._gammaSetter(String(deviceOrientation.gamma));

    cellElement.appendChild(UI.createTextButton(
        Common.UIString('Reset'), this._resetDeviceOrientation.bind(this), 'orientation-reset-button'));
    return fieldsetElement;
  }

  /**
   * @param {!SDK.EmulationModel.DeviceOrientation} deviceOrientation
   * @param {boolean} animate
   */
  _setBoxOrientation(deviceOrientation, animate) {
    if (animate)
      this._stageElement.classList.add('is-animating');
    else
      this._stageElement.classList.remove('is-animating');

    // The CSS transform should not depend on matrix3d, which does not interpolate well.
    const matrix = new WebKitCSSMatrix();
    this._boxMatrix = matrix.rotate(-deviceOrientation.beta, deviceOrientation.gamma, -deviceOrientation.alpha);
    const eulerAngles =
        new UI.Geometry.EulerAngles(deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gamma);
    this._orientationLayer.style.transform = eulerAngles.toRotate3DString();
  }

  /**
   * @param {!MouseEvent} event
   * @return {boolean}
   */
  _onBoxDrag(event) {
    const mouseMoveVector = this._calculateRadiusVector(event.x, event.y);
    if (!mouseMoveVector)
      return true;

    event.consume(true);
    let axis, angle;
    if (event.shiftKey) {
      axis = new UI.Geometry.Vector(0, 0, -1);
      angle = (this._mouseDownVector.x - mouseMoveVector.x) * Emulation.SensorsView.ShiftDragOrientationSpeed;
    } else {
      axis = UI.Geometry.crossProduct(this._mouseDownVector, mouseMoveVector);
      angle = UI.Geometry.calculateAngle(this._mouseDownVector, mouseMoveVector);
    }

    // The mouse movement vectors occur in the screen space, which is offset by 90 degrees from
    // the actual device orientation.
    let currentMatrix = new WebKitCSSMatrix();
    currentMatrix = currentMatrix.rotate(-90, 0, 0)
                        .rotateAxisAngle(axis.x, axis.y, axis.z, angle)
                        .rotate(90, 0, 0)
                        .multiply(this._originalBoxMatrix);

    const eulerAngles = UI.Geometry.EulerAngles.fromRotationMatrix(currentMatrix);
    const newOrientation =
        new SDK.EmulationModel.DeviceOrientation(-eulerAngles.alpha, -eulerAngles.beta, eulerAngles.gamma);
    this._setDeviceOrientation(newOrientation, Emulation.SensorsView.DeviceOrientationModificationSource.UserDrag);
    this._setSelectElementLabel(this._orientationSelectElement, Emulation.SensorsView.NonPresetOptions.Custom);
    return false;
  }

  /**
   * @param {!MouseEvent} event
   * @return {boolean}
   */
  _onBoxDragStart(event) {
    if (!this._deviceOrientationOverrideEnabled)
      return false;

    this._mouseDownVector = this._calculateRadiusVector(event.x, event.y);
    this._originalBoxMatrix = this._boxMatrix;

    if (!this._mouseDownVector)
      return false;

    event.consume(true);
    return true;
  }

  /**
   * @param {number} x
   * @param {number} y
   * @return {?UI.Geometry.Vector}
   */
  _calculateRadiusVector(x, y) {
    const rect = this._stageElement.getBoundingClientRect();
    const radius = Math.max(rect.width, rect.height) / 2;
    const sphereX = (x - rect.left - rect.width / 2) / radius;
    const sphereY = (y - rect.top - rect.height / 2) / radius;
    const sqrSum = sphereX * sphereX + sphereY * sphereY;
    if (sqrSum > 0.5)
      return new UI.Geometry.Vector(sphereX, sphereY, 0.5 / Math.sqrt(sqrSum));

    return new UI.Geometry.Vector(sphereX, sphereY, Math.sqrt(1 - sqrSum));
  }

  _appendTouchControl() {
    const groupElement = this.contentElement.createChild('div', 'sensors-group');
    const title = groupElement.createChild('div', 'sensors-group-title');
    const fieldsElement = groupElement.createChild('div', 'sensors-group-fields');

    title.textContent = Common.UIString('Touch');
    const select = fieldsElement.createChild('select', 'chrome-select');
    select.appendChild(new Option(Common.UIString('Device-based'), 'auto'));
    select.appendChild(new Option(Common.UIString('Force enabled'), 'enabled'));
    select.addEventListener('change', applyTouch, false);

    const reloadWarning = groupElement.createChild('div', 'reload-warning hidden');
    reloadWarning.textContent = Common.UIString('*Requires reload');

    function applyTouch() {
      for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
        emulationModel.overrideEmulateTouch(select.value === 'enabled');
      reloadWarning.classList.remove('hidden');
      const resourceTreeModel = SDK.targetManager.models(SDK.ResourceTreeModel)[0];
      if (resourceTreeModel) {
        resourceTreeModel.once(SDK.ResourceTreeModel.Events.MainFrameNavigated)
            .then(() => reloadWarning.classList.add('hidden'));
      }
    }
  }
};

/** @enum {string} */
Emulation.SensorsView.DeviceOrientationModificationSource = {
  UserInput: 'userInput',
  UserDrag: 'userDrag',
  ResetButton: 'resetButton',
  SelectPreset: 'selectPreset'
};

/** {string} */
Emulation.SensorsView.NonPresetOptions = {
  'NoOverride': 'noOverride',
  'Custom': 'custom',
  'Unavailable': 'unavailable'
};

/** @type {!Array.<{title: string, value: !Array.<{title: string, location: string}>}>} */
Emulation.SensorsView.PresetLocations = [
  {
    title: 'Presets',
    value: [
      {title: Common.UIString('Berlin'), location: '[52.520007, 13.404954]'},
      {title: Common.UIString('London'), location: '[51.507351, -0.127758]'},
      {title: Common.UIString('Moscow'), location: '[55.755826, 37.617300]'},
      {title: Common.UIString('Mountain View'), location: '[37.386052, -122.083851]'},
      {title: Common.UIString('Mumbai'), location: '[19.075984, 72.877656]'},
      {title: Common.UIString('San Francisco'), location: '[37.774929, -122.419416]'},
      {title: Common.UIString('Shanghai'), location: '[31.230416, 121.473701]'},
      {title: Common.UIString('São Paulo'), location: '[-23.550520, -46.633309]'},
      {title: Common.UIString('Tokyo'), location: '[35.689487, 139.691706]'},
    ]
  },
  {
    title: 'Error',
    value: [
      {title: Common.UIString('Location unavailable'), location: Emulation.SensorsView.NonPresetOptions.Unavailable}
    ]
  }
];

/** @type {!Array.<{title: string, value: !Array.<{title: string, orientation: string}>}>} */
Emulation.SensorsView.PresetOrientations = [{
  title: 'Presets',
  value: [
    {title: Common.UIString('Portrait'), orientation: '[0, 90, 0]'},
    {title: Common.UIString('Portrait upside down'), orientation: '[180, -90, 0]'},
    {title: Common.UIString('Landscape left'), orientation: '[0, 90, -90]'},
    {title: Common.UIString('Landscape right'), orientation: '[0, 90, 90]'},
    {title: Common.UIString('Display up'), orientation: '[0, 0, 0]'},
    {title: Common.UIString('Display down'), orientation: '[0, 180, 0]'}
  ]
}];


/**
 * @implements {UI.ActionDelegate}
 * @unrestricted
 */
Emulation.SensorsView.ShowActionDelegate = class {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    UI.viewManager.showView('sensors');
    return true;
  }
};

Emulation.SensorsView.ShiftDragOrientationSpeed = 16;
