import { computed, set } from "@ember/object";
import Category from "discourse/models/category";
import ComboBoxComponent from "select-kit/components/combo-box";
import I18n from "I18n";
import PermissionType from "discourse/models/permission-type";
import { categoryBadgeHTML } from "discourse/helpers/category-link";
import { isNone } from "@ember/utils";
import { setting } from "discourse/lib/computed";

export default ComboBoxComponent.extend({
  pluginApiIdentifiers: ["category-chooser"],
  classNames: ["category-chooser"],
  allowUncategorizedTopics: setting("allow_uncategorized_topics"),
  fixedCategoryPositionsOnCreate: setting("fixed_category_positions_on_create"),

  selectKitOptions: {
    filterable: true,
    allowUncategorized: false,
    allowSubCategories: true,
    permissionType: PermissionType.FULL,
    excludeCategoryId: null,
    scopedCategoryId: null,
  },

  modifyComponentForRow() {
    return "category-row";
  },

  modifyNoSelection() {
    if (!isNone(this.selectKit.options.none)) {
      const none = this.selectKit.options.none;
      const isString = typeof none === "string";
      return this.defaultItem(
        null,
        I18n.t(
          isString ? this.selectKit.options.none : "category.none"
        ).htmlSafe()
      );
    } else if (
      this.allowUncategorizedTopics ||
      this.selectKit.options.allowUncategorized
    ) {
      return Category.findUncategorized();
    } else {
      return this.defaultItem(null, I18n.t("category.choose").htmlSafe());
    }
  },

  modifySelection(content) {
    if (this.selectKit.hasSelection) {
      const category = Category.findById(this.value);

      set(
        content,
        "label",
        categoryBadgeHTML(category, {
          link: false,
          hideParent: category ? !!category.parent_category_id : true,
          allowUncategorized: true,
          recursive: true,
        }).htmlSafe()
      );
    }

    return content;
  },

  search(filter) {
    if (filter) {
      filter = this._normalize(filter);
      return this.content.filter((item) => {
        const category = Category.findById(this.getValue(item));
        const categoryName = this.getName(item);

        if (category && category.parentCategory) {
          const parentCategoryName = this.getName(category.parentCategory);
          return (
            this._matchCategory(filter, categoryName) ||
            this._matchCategory(filter, parentCategoryName)
          );
        } else {
          return this._matchCategory(filter, categoryName);
        }
      });
    } else {
      return this.content;
    }
  },

  content: computed(
    "selectKit.filter",
    "selectKit.options.scopedCategoryId",
    function () {
      if (!this.selectKit.filter && this.selectKit.options.scopedCategoryId) {
        return this.categoriesByScope(this.selectKit.options.scopedCategoryId);
      } else {
        return this.categoriesByScope();
      }
    }
  ),

  categoriesByScope(scopedCategoryId = null) {
    const categories = this.fixedCategoryPositionsOnCreate
      ? Category.list()
      : Category.listByActivity();

    if (scopedCategoryId) {
      const scopedCat = Category.findById(scopedCategoryId);
      scopedCategoryId = scopedCat.parent_category_id || scopedCat.id;
    }

    const excludeCategoryId = this.selectKit.options.excludeCategoryId;

    return categories.filter((category) => {
      const categoryId = this.getValue(category);

      if (
        scopedCategoryId &&
        categoryId !== scopedCategoryId &&
        category.parent_category_id !== scopedCategoryId
      ) {
        return false;
      }

      if (
        this.selectKit.options.allowSubCategories === false &&
        category.parentCategory
      ) {
        return false;
      }

      if (
        (this.selectKit.options.allowUncategorized === false &&
          category.isUncategorizedCategory) ||
        excludeCategoryId === categoryId
      ) {
        return false;
      }

      const permissionType = this.selectKit.options.permissionType;
      if (permissionType && !this.allowRestrictedCategories) {
        return permissionType === category.permission;
      }

      return true;
    });
  },

  _matchCategory(filter, categoryName) {
    return this._normalize(categoryName).indexOf(filter) > -1;
  },
});
