import { later } from "@ember/runloop";
import { createWidget, applyDecorators } from "discourse/widgets/widget";
import { h } from "virtual-dom";
import DiscourseURL from "discourse/lib/url";
import { ajax } from "discourse/lib/ajax";
import { userPath } from "discourse/lib/url";
import { NotificationLevels } from "discourse/lib/notification-levels";

const flatten = array => [].concat.apply([], array);

createWidget("priority-faq-link", {
  tagName: "a.faq-priority.widget-link",

  buildAttributes(attrs) {
    return { href: attrs.href };
  },

  html() {
    return [
      I18n.t("faq"),
      " ",
      h("span.badge.badge-notification", I18n.t("new_item"))
    ];
  },

  click(e) {
    e.preventDefault();
    if (this.siteSettings.faq_url === this.attrs.href) {
      ajax(userPath("read-faq"), { method: "POST" }).then(() => {
        this.currentUser.set("read_faq", true);
        DiscourseURL.routeToTag($(e.target).closest("a")[0]);
      });
    } else {
      DiscourseURL.routeToTag($(e.target).closest("a")[0]);
    }
  }
});

export default createWidget("hamburger-menu", {
  tagName: "div.hamburger-panel",

  settings: {
    showCategories: true,
    maxWidth: 320,
    showFAQ: true,
    showAbout: true
  },

  adminLinks() {
    const { currentUser } = this;

    const links = [
      {
        route: "admin",
        className: "admin-link",
        icon: "wrench",
        label: "admin_title"
      }
    ];

    if (currentUser.admin) {
      links.push({
        href: "/admin/site_settings",
        icon: "cog",
        label: "admin.site_settings.title",
        className: "settings-link"
      });
    }

    return links.map(l => this.attach("link", l));
  },

  lookupCount(type) {
    const tts = this.register.lookup("topic-tracking-state:main");
    return tts ? tts.lookupCount(type) : 0;
  },

  showUserDirectory() {
    if (!this.siteSettings.enable_user_directory) return false;
    if (this.siteSettings.hide_user_profiles_from_public && !this.currentUser)
      return false;
    return true;
  },

  generalLinks() {
    const { siteSettings } = this;
    const links = [];

    links.push({
      route: "discovery.latest",
      className: "latest-topics-link",
      label: "filters.latest.title",
      title: "filters.latest.help"
    });

    if (this.currentUser) {
      links.push({
        route: "discovery.new",
        className: "new-topics-link",
        labelCount: "filters.new.title_with_count",
        label: "filters.new.title",
        title: "filters.new.help",
        count: this.lookupCount("new")
      });

      links.push({
        route: "discovery.unread",
        className: "unread-topics-link",
        labelCount: "filters.unread.title_with_count",
        label: "filters.unread.title",
        title: "filters.unread.help",
        count: this.lookupCount("unread")
      });
    }

    // Staff always see the review link. Non-staff will see it if there are items to review
    if (
      this.currentUser &&
      (this.currentUser.staff || this.currentUser.reviewable_count)
    ) {
      links.push({
        route: siteSettings.reviewable_default_topics
          ? "review.topics"
          : "review",
        className: "review",
        label: "review.title",
        badgeCount: "reviewable_count",
        badgeClass: "reviewables"
      });
    }

    links.push({
      route: "discovery.top",
      className: "top-topics-link",
      label: "filters.top.title",
      title: "filters.top.help"
    });

    if (siteSettings.enable_badges) {
      links.push({
        route: "badges",
        className: "badge-link",
        label: "badges.title"
      });
    }

    if (this.showUserDirectory()) {
      links.push({
        route: "users",
        className: "user-directory-link",
        label: "directory.title"
      });
    }

    if (this.siteSettings.enable_group_directory) {
      links.push({
        route: "groups",
        className: "groups-link",
        label: "groups.index.title"
      });
    }

    if (this.siteSettings.tagging_enabled) {
      links.push({ route: "tags", label: "tagging.tags" });
    }

    const extraLinks = flatten(
      applyDecorators(this, "generalLinks", this.attrs, this.state)
    );
    return links.concat(extraLinks).map(l => this.attach("link", l));
  },

  listCategories() {
    const maxCategoriesToDisplay = this.siteSettings
      .header_dropdown_category_count;
    let categories = [];

    if (this.currentUser) {
      const allCategories = this.site
        .get("categories")
        .filter(c => c.notification_level !== NotificationLevels.MUTED);

      categories = allCategories
        .filter(c => c.get("newTopics") > 0 || c.get("unreadTopics") > 0)
        .sort((a, b) => {
          return (
            b.get("newTopics") +
            b.get("unreadTopics") -
            (a.get("newTopics") + a.get("unreadTopics"))
          );
        });

      const topCategoryIds = this.currentUser.get("top_category_ids") || [];
      topCategoryIds.forEach(id => {
        const category = allCategories.find(c => c.id === id);
        if (category && !categories.includes(category)) {
          categories.push(category);
        }
      });

      categories = categories.concat(
        allCategories
          .filter(c => !categories.includes(c))
          .sort((a, b) => b.topic_count - a.topic_count)
      );
    } else {
      categories = this.site
        .get("categoriesByCount")
        .filter(c => c.notification_level !== NotificationLevels.MUTED);
    }

    if (!this.siteSettings.allow_uncategorized_topics) {
      categories = categories.filter(
        c => c.id !== this.site.uncategorized_category_id
      );
    }

    const moreCount = categories.length - maxCategoriesToDisplay;
    categories = categories.slice(0, maxCategoriesToDisplay);

    return this.attach("hamburger-categories", { categories, moreCount });
  },

  footerLinks(prioritizeFaq, faqUrl) {
    const links = [];
    if (this.settings.showAbout) {
      links.push({
        route: "about",
        className: "about-link",
        label: "about.simple_title"
      });
    }

    if (this.settings.showFAQ && !prioritizeFaq) {
      links.push({ href: faqUrl, className: "faq-link", label: "faq" });
    }

    const { site } = this;
    if (!site.mobileView && !this.capabilities.touch) {
      links.push({
        href: "",
        action: "showKeyboard",
        className: "keyboard-shortcuts-link",
        label: "keyboard_shortcuts_help.title"
      });
    }

    if (
      this.site.mobileView ||
      (this.siteSettings.enable_mobile_theme && this.capabilities.touch)
    ) {
      links.push({
        action: "toggleMobileView",
        className: "mobile-toggle-link",
        label: this.site.mobileView ? "desktop_view" : "mobile_view"
      });
    }

    const extraLinks = flatten(
      applyDecorators(this, "footerLinks", this.attrs, this.state)
    );
    return links.concat(extraLinks).map(l => this.attach("link", l));
  },

  panelContents() {
    const { currentUser } = this;
    const results = [];

    let faqUrl = this.siteSettings.faq_url;
    if (!faqUrl || faqUrl.length === 0) {
      faqUrl = Discourse.getURL("/faq");
    }

    const prioritizeFaq =
      this.settings.showFAQ && this.currentUser && !this.currentUser.read_faq;

    if (prioritizeFaq) {
      results.push(
        this.attach("menu-links", {
          name: "faq-link",
          heading: true,
          contents: () => {
            return this.attach("priority-faq-link", { href: faqUrl });
          }
        })
      );
    }

    if (currentUser && currentUser.staff) {
      results.push(
        this.attach("menu-links", {
          name: "admin-links",
          contents: () => {
            const extraLinks = flatten(
              applyDecorators(this, "admin-links", this.attrs, this.state)
            );
            return this.adminLinks().concat(extraLinks);
          }
        })
      );
    }

    results.push(
      this.attach("menu-links", {
        name: "general-links",
        contents: () => this.generalLinks()
      })
    );

    if (this.settings.showCategories) {
      results.push(this.listCategories());
      results.push(h("hr.categories-separator"));
    }

    results.push(
      this.attach("menu-links", {
        name: "footer-links",
        omitRule: true,
        contents: () => this.footerLinks(prioritizeFaq, faqUrl)
      })
    );

    return results;
  },

  html() {
    return this.attach("menu-panel", {
      contents: () => this.panelContents(),
      maxWidth: this.settings.maxWidth
    });
  },

  clickOutsideMobile(e) {
    const $centeredElement = $(document.elementFromPoint(e.clientX, e.clientY));
    if (
      $centeredElement.parents(".panel").length &&
      !$centeredElement.hasClass("header-cloak")
    ) {
      this.sendWidgetAction("toggleHamburger");
    } else {
      const $window = $(window);
      const windowWidth = $window.width();
      const $panel = $(".menu-panel");
      $panel.addClass("animate");
      const panelOffsetDirection = this.site.mobileView ? "left" : "right";
      $panel.css(panelOffsetDirection, -windowWidth);
      const $headerCloak = $(".header-cloak");
      $headerCloak.addClass("animate");
      $headerCloak.css("opacity", 0);
      later(() => this.sendWidgetAction("toggleHamburger"), 200);
    }
  },

  clickOutside(e) {
    if (this.site.mobileView) {
      this.clickOutsideMobile(e);
    } else {
      this.sendWidgetAction("toggleHamburger");
    }
  }
});
