import Ember from 'ember';
import TooltipAndPopoverComponent from 'ember-tooltips/components/tooltip-and-popover';
import layout from 'ember-tooltips/templates/components/popover-on-element';

const { $, run } = Ember;

export default TooltipAndPopoverComponent.extend({

  hideDelay: '250',

  layout,
  classNames: ['ember-popover'],
  _isMouseInside: false,
  didInsertElement() {
    this._super(...arguments);

    const event = this.get('event');
    const target = this.get('target');
    const $target = $(target);
    const $popover = this.$();

    if (event === 'none') {

      return;

    } else if (event === 'hover') {

      const _showOn = this.get('_showOn');
      const _hideOn = this.get('_hideOn');

      // _showOn == 'mouseenter'
      $target.on(_showOn, () => this.show());

      // _hideOn == 'mouseleave'
      $target.add($popover).on(_hideOn, () => {
        run.later(() => {
          if (!this.get('_isMouseInside')) {
            this.hide();
          }
        }, +this.get('hideDelay'));
      });

      // we must use mouseover/mouseout because they correctly
      // register hover interactivity when spacing='0'
      $target.add($popover).on('mouseover', () => this.set('_isMouseInside', true));
      $target.add($popover).on('mouseout', () => this.set('_isMouseInside', false));

    } else if (event === 'click') {

      $(document).on(`click.${target}`, (event) => {
        // this lightweight, name-spaced click handler is necessary to determine
        // if a click is NOT on $target and NOT an ancestor of $target.
        // If so then it must be a click elsewhere and should close the popover
        // see... https://css-tricks.com/dangers-stopping-event-propagation/
        const clickedElement = event.target;
        const isClickOutsideTarget = $target[0] !== clickedElement;
        const isClickOutsidePopover = !$target.find(clickedElement).length;
        const isShown = this.get('isShown');

        if (isClickOutsideTarget && isClickOutsidePopover && isShown) {
          this.hide();
        }
      });

      // we use mousedown because it occurs before the focus event
      $target.on('mousedown', (event) => {
        // $target.on('mousedown') is called when the $popover is
        // clicked because the $popover is contained within the $target.
        // This will ignores those types of clicks.
        if ($popover[0] === event.target || $popover.find(event.target).length) {
          return;
        }
        this.toggle();
      });
    }

    $target.on('focus', () => this.show());

    $popover.on('focusout', () => {
      // use a run.later() to allow the 'focusout' event to finish handling
      run.later(() => {
        const focusedElement = document.activeElement;
        const isFocusedElementTarget = focusedElement === $target[0];
        const isFocusedElementPopover = focusedElement === $popover[0];
        const isFocusedElementInPopover = !!$popover.find(focusedElement).length;
        if (isFocusedElementTarget || isFocusedElementPopover || isFocusedElementInPopover) {
          return;
        }
        this.hide();
      });
    });
  },
  willDestroyElement() {
    this._super(...arguments);

    const target = this.get('target');
    const $target = $(target);
    const $popover = this.$();
    const _showOn = this.get('_showOn');
    const _hideOn = this.get('_hideOn');

    $target.add($popover).off(`${_showOn} mouseover ${_hideOn} mouseout mousedown focus focusout`);

    $(document).off(`click.${target}`);

  },
  actions: {
    hide() {
      this.hide();
    }
  },

});

@@ -1735,17 +1735,19 @@
   const 
-c
+isC
 lickedEl
@@ -1755,167 +1755,58 @@
 ment
- = event.target;%0A        const isClickOutsideTarget = $target%5B0%5D !== clickedElement;%0A        const isClickOutsidePopover = !$target.find(clickedElement).length
+Elsewhere = this._isElementElsewhere(event.target)
 ;%0A  
@@ -1819,16 +1819,23 @@
 const is
+Popover
 Shown = 
@@ -1879,52 +1879,39 @@
 lick
-OutsideTarget && isClickOutside
+edElementElsewhere && is
 Popover
- && is
 Show
@@ -2272,57 +2272,68 @@
     
-if ($popover%5B0%5D === event.target %7C%7C $p
+const isMouseDownElementInPopover = this._isElementInP
 opover
-.find
 (eve
@@ -2342,23 +2342,57 @@
 .target)
-.length
+;%0A        if (isMouseDownElementInPopover
 ) %7B%0A    
@@ -2654,264 +2654,84 @@
 nst 
-focusedElement = document.activeElement;%0A        const isFocusedElementTarget = focusedElement === $target%5B0%5D;%0A        const isFocusedElementPopover = focusedElement === $popover%5B0%5D;%0A        const isFocusedElementInPopover = !!$popover.find(focused
+isFocusedElementElsewhere = this._isElementElsewhere(document.active
 Element)
 .len
@@ -2730,15 +2730,8 @@
 ent)
-.length
 ;%0A  
@@ -2760,70 +2760,17 @@
 ment
-Target %7C%7C isFocusedElementPopover %7C%7C isFocusedElementInPopov
+Elsewh
 er
+e
 ) %7B%0A
@@ -2783,34 +2783,8 @@
     
-return;%0A        %7D%0A        
 this
@@ -2787,24 +2787,34 @@
 this.hide();
+%0A        %7D
 %0A      %7D);%0A 
@@ -3207,16 +3207,657 @@
 get%7D%60);%0A
+  %7D,%0A  _isElementInPopover(newElement) %7B%0A    // determines if newElement is $popover or contained within $popover%0A    const $popover = this.$();%0A    return $popover.is(newElement) %7C%7C $popover.find(newElement).length;%0A  %7D,%0A  _isElementElsewhere(newElement) %7B%0A    // determines if newElement is not $target, not $popover, and not contained within either%0A    const $target = $(this.get('target'));%0A%0A    const isNewElementOutsideTarget = !$target.is(newElement) && !$target.find(newElement).length;%0A    const isNewElementOutsidePopover = !this._isElementInPopover(newElement);%0A%0A    return isNewElementOutsideTarget && isNewElementOutsidePopover;
 %0A  %7D,%0A  
@@ -3910,13 +3910,12 @@
  %7D%0A  %7D,%0A
-%0A
 %7D);%0A

use .in & check popover.in and popover.find