// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
(function(window) {
  'use strict';

  const BOTTOM_OFFSET = 7.2; // Height of the arrow in tooltip.

  /** @polymerBehavior Gerrit.TooltipBehavior */
  const TooltipBehavior = {

    properties: {
      hasTooltip: {
        type: Boolean,
        observer: '_setupTooltipListeners',
      },

      _isTouchDevice: {
        type: Boolean,
        value() {
          return 'ontouchstart' in document.documentElement;
        },
      },
      _tooltip: Element,
      _titleText: String,
      _hasSetupTooltipListeners: {
        type: Boolean,
        value: false,
      },
    },

    detached() {
      this._handleHideTooltip();
      this.unlisten(window, 'scroll', '_handleWindowScroll');
    },

    _setupTooltipListeners() {
      if (this._hasSetupTooltipListeners || !this.hasTooltip) { return; }
      this._hasSetupTooltipListeners = true;

      this.addEventListener('mouseenter', this._handleShowTooltip.bind(this));
      this.addEventListener('mouseleave', this._handleHideTooltip.bind(this));
      this.addEventListener('tap', this._handleHideTooltip.bind(this));
      this.listen(window, 'scroll', '_handleWindowScroll');
    },

    _handleShowTooltip(e) {
      if (this._isTouchDevice) { return; }

      if (!this.hasAttribute('title') ||
          this.getAttribute('title') === '' ||
          this._tooltip) {
        return;
      }

      // Store the title attribute text then set it to an empty string to
      // prevent it from showing natively.
      this._titleText = this.getAttribute('title');
      this.setAttribute('title', '');

      const tooltip = document.createElement('gr-tooltip');
      tooltip.text = this._titleText;
      tooltip.maxWidth = this.getAttribute('max-width');

      // Set visibility to hidden before appending to the DOM so that
      // calculations can be made based on the element’s size.
      tooltip.style.visibility = 'hidden';
      Gerrit.getRootElement().appendChild(tooltip);
      this._positionTooltip(tooltip);
      tooltip.style.visibility = null;

      this._tooltip = tooltip;
    },

    _handleHideTooltip(e) {
      if (this._isTouchDevice) { return; }
      if (!this.hasAttribute('title') ||
          this._titleText == null) {
        return;
      }

      this.setAttribute('title', this._titleText);
      if (this._tooltip && this._tooltip.parentNode) {
        this._tooltip.parentNode.removeChild(this._tooltip);
      }
      this._tooltip = null;
    },

    _handleWindowScroll(e) {
      if (!this._tooltip) { return; }

      this._positionTooltip(this._tooltip);
    },

    _positionTooltip(tooltip) {
      const rect = this.getBoundingClientRect();
      const boxRect = tooltip.getBoundingClientRect();
      const parentRect = tooltip.parentElement.getBoundingClientRect();
      const top = rect.top - parentRect.top;
      const left =
          rect.left - parentRect.left + (rect.width - boxRect.width) / 2;
      const right = parentRect.width - left - boxRect.width;
      if (left < 0) {
        tooltip.updateStyles({
          '--gr-tooltip-arrow-center-offset': left + 'px',
        });
      } else if (right < 0) {
        tooltip.updateStyles({
          '--gr-tooltip-arrow-center-offset': (-0.5 * right) + 'px',
        });
      }
      tooltip.style.left = Math.max(0, left) + 'px';
      tooltip.style.top = Math.max(0, top) + 'px';
      tooltip.style.transform = 'translateY(calc(-100% - ' + BOTTOM_OFFSET +
          'px))';
    },
  };

  window.Gerrit = window.Gerrit || {};
  window.Gerrit.TooltipBehavior = TooltipBehavior;
})(window);
