import MountWidget from 'discourse/components/mount-widget';
import { observes } from 'ember-addons/ember-computed-decorators';
import Docking from 'discourse/mixins/docking';

const _flagProperties = [];
function addFlagProperty(prop) {
  _flagProperties.pushObject(prop);
}

const PANEL_BODY_MARGIN = 30;

const SiteHeaderComponent = MountWidget.extend(Docking, {
  widget: 'header',
  docAt: null,
  dockedHeader: null,
  _topic: null,

  @observes('currentUser.unread_notifications', 'currentUser.unread_private_messages')
  _notificationsChanged() {
    this.queueRerender();
  },

  dockCheck(info) {
    if (this.docAt === null) {
      const outlet = $('#main-outlet');
      if (!(outlet && outlet.length === 1)) return;
      this.docAt = outlet.offset().top;
    }

    const $body = $('body');
    const offset = info.offset();
    if (offset >= this.docAt) {
      if (!this.dockedHeader) {
        $body.addClass('docked');
        this.dockedHeader = true;
      }
    } else {
      if (this.dockedHeader) {
        $body.removeClass('docked');
        this.dockedHeader = false;
      }
    }
  },

  setTopic(topic) {
    this._topic = topic;
    this.queueRerender();
  },

  didInsertElement() {
    this._super();
    $(window).on('resize.discourse-menu-panel', () => this.afterRender());

    this.appEvents.on('header:show-topic', topic => this.setTopic(topic));
    this.appEvents.on('header:hide-topic', () => this.setTopic(null));

    this.dispatch('notifications:changed', 'user-notifications');
    this.dispatch('header:keyboard-trigger', 'header');

    this.appEvents.on('dom:clean', () => {
      // For performance, only trigger a re-render if any menu panels are visible
      if (this.$('.menu-panel').length) {
        this.eventDispatched('dom:clean', 'header');
      }
    });
  },

  willDestroyElement() {
    this._super();
    $('body').off('keydown.header');
    $(window).off('resize.discourse-menu-panel');

    this.appEvents.off('header:show-topic');
    this.appEvents.off('header:hide-topic');
    this.appEvents.off('dom:clean');
  },

  buildArgs() {
    return {
      flagCount: _flagProperties.reduce((prev, cur) => prev + (this.get(cur) || 0), 0),
      topic: this._topic,
      canSignUp: this.get('canSignUp')
    };
  },

  afterRender() {
    const $menuPanels = $('.menu-panel');
    if ($menuPanels.length === 0) { return; }

    const $window = $(window);
    const windowWidth = parseInt($window.width());


    const headerWidth = $('#main-outlet .container').width() || 1100;
    const remaining = parseInt((windowWidth - headerWidth) / 2);
    const viewMode = (remaining < 50) ? 'slide-in' : 'drop-down';

    $menuPanels.each((idx, panel) => {
      const $panel = $(panel);
      let width = parseInt($panel.attr('data-max-width') || 300);
      if ((windowWidth - width) < 50) {
        width = windowWidth - 50;
      }

      $panel.removeClass('drop-down').removeClass('slide-in').addClass(viewMode);

      const $panelBody = $('.panel-body', $panel);
      let contentHeight = parseInt($('.panel-body-contents', $panel).height());

      // We use a mutationObserver to check for style changes, so it's important
      // we don't set it if it doesn't change. Same goes for the $panelBody!
      const style = $panel.prop('style');

      if (viewMode === 'drop-down') {
        const $buttonPanel = $('header ul.icons');
        if ($buttonPanel.length === 0) { return; }

        // These values need to be set here, not in the css file - this is to deal with the
        // possibility of the window being resized and the menu changing from .slide-in to .drop-down.
        if (style.top !== '100%' || style.height !== 'auto') {
          $panel.css({ top: '100%', height: 'auto' });
        }

        // adjust panel height
        const fullHeight = parseInt($window.height());
        const offsetTop = $panel.offset().top;
        const scrollTop = $window.scrollTop();

        if (contentHeight + (offsetTop - scrollTop) + PANEL_BODY_MARGIN > fullHeight) {
          contentHeight = fullHeight - (offsetTop - scrollTop) - PANEL_BODY_MARGIN;
        }
        if ($panelBody.height() !== contentHeight) {
          $panelBody.height(contentHeight);
        }
        $('body').addClass('drop-down-visible');
      } else {
        const menuTop = headerHeight();

        let height;
        const winHeight = $(window).height() - 16;
        if ((menuTop + contentHeight) < winHeight) {
          height = contentHeight + "px";
        } else {
          height = winHeight - menuTop;
        }

        if ($panelBody.prop('style').height !== '100%') {
          $panelBody.height('100%');
        }
        if (style.top !== menuTop + "px" || style.height !== height) {
          $panel.css({ top: menuTop + "px", height });
        }
        $('body').removeClass('drop-down-visible');
      }

      $panel.width(width);
    });
  }
});

export default SiteHeaderComponent;

function applyFlaggedProperties() {
  const args = _flagProperties.slice();
  args.push(function() {
    this.queueRerender();
  }.on('init'));

  SiteHeaderComponent.reopen({ _flagsChanged: Ember.observer.apply(this, args) });
}

addFlagProperty('currentUser.site_flagged_posts_count');
addFlagProperty('currentUser.post_queue_new_count');

export { addFlagProperty, applyFlaggedProperties };

export function headerHeight() {
  const $header = $('header.d-header');
  const headerOffset = $header.offset();
  const headerOffsetTop = (headerOffset) ? headerOffset.top : 0;
  return parseInt($header.outerHeight() + headerOffsetTop - $(window).scrollTop());
}
