// 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
 */
export default class SensorsView 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 {!SensorsView}
   */
  static instance() {
    if (!SensorsView._instanceObject) {
      SensorsView._instanceObject = new SensorsView();
    }
    return SensorsView._instanceObject;
  }

  /**
   * @param {!SDK.EmulationModel.Geolocation} geolocation
   */
  _createGeolocationSection(geolocation) {
    const geogroup = this.contentElement.createChild('section', 'sensors-group');
    const geogroupTitle = UI.createLabel(ls`Geolocation`, 'sensors-group-title');
    geogroup.appendChild(geogroupTitle);
    const fields = geogroup.createChild('div', 'geo-fields');

    const noOverrideOption = {title: Common.UIString('No override'), location: NonPresetOptions.NoOverride};

    this._locationSelectElement = fields.createChild('select', 'chrome-select');
    UI.ARIAUtils.bindLabelToControl(geogroupTitle, this._locationSelectElement);

    // No override
    this._locationSelectElement.appendChild(new Option(noOverrideOption.title, noOverrideOption.location));

    // Locations
    this._customLocationsGroup = this._locationSelectElement.createChild('optgroup');
    this._customLocationsGroup.label = ls`Overrides`;
    const customGeolocations = Common.moduleSetting('emulation.geolocations');
    const manageButton = UI.createTextButton(ls`Manage`, () => Common.Revealer.reveal(customGeolocations));
    UI.ARIAUtils.setAccessibleName(manageButton, ls`Manage the list of geolocations`);
    fields.appendChild(manageButton);
    const fillCustomSettings = () => {
      this._customLocationsGroup.removeChildren();
      for (const geolocation of customGeolocations.get()) {
        this._customLocationsGroup.appendChild(new Option(geolocation.title, JSON.stringify(geolocation)));
      }
    };
    customGeolocations.addChangeListener(fillCustomSettings);
    fillCustomSettings();

    // Other location
    const customLocationOption = {title: Common.UIString('Other\u2026'), location: NonPresetOptions.Custom};
    this._locationSelectElement.appendChild(new Option(customLocationOption.title, customLocationOption.location));

    // Error location.
    const group = this._locationSelectElement.createChild('optgroup');
    group.label = ls`Error`;
    group.appendChild(new Option(ls`Location unavailable`, NonPresetOptions.Unavailable));

    this._locationSelectElement.selectedIndex = 0;
    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');
    const timezoneGroup = this._fieldsetElement.createChild('div', 'latlong-group');

    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 = 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._latitudeInput.title = modifierKeyMessage;
    latitudeGroup.appendChild(UI.createLabel(ls`Latitude`, 'latlong-title', this._latitudeInput));

    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));
    this._longitudeInput.title = modifierKeyMessage;
    longitudeGroup.appendChild(UI.createLabel(ls`Longitude`, 'latlong-title', this._longitudeInput));

    this._timezoneInput = UI.createInput('', 'text');
    timezoneGroup.appendChild(this._timezoneInput);
    this._timezoneInput.value = 'Europe/Berlin';
    this._timezoneSetter = UI.bindInput(
        this._timezoneInput, this._applyGeolocationUserInput.bind(this),
        SDK.EmulationModel.Geolocation.timezoneIdValidator, false);
    this._timezoneSetter(String(geolocation.timezoneId));
    timezoneGroup.appendChild(UI.createLabel(ls`Timezone ID`, 'timezone-title', this._timezoneInput));
    this._timezoneError = timezoneGroup.createChild('div', 'timezone-error');
  }

  _geolocationSelectChanged() {
    this._fieldsetElement.disabled = false;
    this._timezoneError.textContent = '';
    const value = this._locationSelectElement.options[this._locationSelectElement.selectedIndex].value;
    if (value === NonPresetOptions.NoOverride) {
      this._geolocationOverrideEnabled = false;
      this._fieldsetElement.disabled = true;
    } else if (value === NonPresetOptions.Custom) {
      this._geolocationOverrideEnabled = true;
      const geolocation = SDK.EmulationModel.Geolocation.parseUserInput(
          this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), this._timezoneInput.value.trim());
      if (!geolocation) {
        return;
      }
      this._geolocation = geolocation;
    } else if (value === 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.lat, coordinates.long, coordinates.timezoneId, false);
      this._latitudeSetter(coordinates.lat);
      this._longitudeSetter(coordinates.long);
      this._timezoneSetter(coordinates.timezoneId);
    }

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

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

    this._timezoneError.textContent = '';

    this._setSelectElementLabel(this._locationSelectElement, 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).catch(err => {
        switch (err.type) {
          case 'emulation-set-timezone':
            this._timezoneError.textContent = err.message;
            break;
        }
      });
    }
  }

  _createDeviceOrientationSection() {
    const orientationGroup = this.contentElement.createChild('section', 'sensors-group');
    const orientationTitle = UI.createLabel(ls`Orientation`, 'sensors-group-title');
    orientationGroup.appendChild(orientationTitle);
    const orientationContent = orientationGroup.createChild('div', 'orientation-content');
    const fields = orientationContent.createChild('div', 'orientation-fields');

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

    const orientationGroups = 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._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');
      this._stageElement.title = ls`Enable orientation to rotate`;
    } else {
      this._deviceOrientationFieldset.disabled = false;
      this._stageElement.classList.remove('disabled');
      this._stageElement.title = ls`Shift+drag horizontally to rotate around the y-axis`;
    }
  }

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

    if (value === NonPresetOptions.NoOverride) {
      this._deviceOrientationOverrideEnabled = false;
      this._enableOrientationFields(true);
    } else if (value === 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, 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()),
        DeviceOrientationModificationSource.UserInput);
    this._setSelectElementLabel(this._orientationSelectElement, NonPresetOptions.Custom);
  }

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

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

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

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

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

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

    UI.ARIAUtils.alert(
        ls`Device orientation set to alpha: ${deviceOrientation.alpha}, beta: ${deviceOrientation.beta}, gamma: ${
            deviceOrientation.gamma}`,
        this._orientationSelectElement);
  }

  /**
   * @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.appendChild(UI.createLabel(label, /* className */ '', input));
    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));

    const resetButton = UI.createTextButton(
        Common.UIString('Reset'), this._resetDeviceOrientation.bind(this), 'orientation-reset-button');
    UI.ARIAUtils.setAccessibleName(resetButton, ls`Reset device orientation`);
    resetButton.setAttribute('type', 'reset');
    cellElement.appendChild(resetButton);
    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) * 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, DeviceOrientationModificationSource.UserDrag);
    this._setSelectElementLabel(this._orientationSelectElement, 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 = UI.createLabel(ls`Touch`, 'sensors-group-title');
    groupElement.appendChild(title);
    const fieldsElement = groupElement.createChild('div', 'sensors-group-fields');

    const select = fieldsElement.createChild('select', 'chrome-select');
    UI.ARIAUtils.bindLabelToControl(title, 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');
    UI.ARIAUtils.markAsAlert(reloadWarning);

    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} */
export const DeviceOrientationModificationSource = {
  UserInput: 'userInput',
  UserDrag: 'userDrag',
  ResetButton: 'resetButton',
  SelectPreset: 'selectPreset'
};

/** {string} */
export const NonPresetOptions = {
  NoOverride: 'noOverride',
  Custom: 'custom',
  Unavailable: 'unavailable'
};

/** @type {!Array.<{title: string, value: !Array.<{title: string, orientation: string}>}>} */
export const PresetOrientations = [{
  title: ls`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
 */
export class ShowActionDelegate {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    UI.viewManager.showView('sensors');
    return true;
  }
}

export const ShiftDragOrientationSpeed = 16;

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

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

/**
 * @constructor
 */
Emulation.SensorsView = SensorsView;

/** @enum {string} */
Emulation.SensorsView.DeviceOrientationModificationSource = DeviceOrientationModificationSource;

/** {string} */
Emulation.SensorsView.NonPresetOptions = NonPresetOptions;

/** @type {!Array.<{title: string, value: !Array.<{title: string, orientation: string}>}>} */
Emulation.SensorsView.PresetOrientations = PresetOrientations;

/**
 * @constructor
 */
Emulation.SensorsView.ShowActionDelegate = ShowActionDelegate;
Emulation.SensorsView.ShiftDragOrientationSpeed = ShiftDragOrientationSpeed;
