<script>
import {
  GlAvatar,
  GlLoadingIcon,
  GlBadge,
  GlIcon,
  GlTooltipDirective,
  GlSafeHtmlDirective,
} from '@gitlab/ui';
import { visitUrl } from '~/lib/utils/url_utility';
import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '../constants';
import eventHub from '../event_hub';

import itemActions from './item_actions.vue';
import itemCaret from './item_caret.vue';
import itemStats from './item_stats.vue';
import itemTypeIcon from './item_type_icon.vue';

export default {
  directives: {
    GlTooltip: GlTooltipDirective,
    SafeHtml: GlSafeHtmlDirective,
  },
  components: {
    GlAvatar,
    GlBadge,
    GlLoadingIcon,
    GlIcon,
    UserAccessRoleBadge,
    ComplianceFrameworkLabel: () =>
      import(
        'ee_component/vue_shared/components/compliance_framework_label/compliance_framework_label.vue'
      ),
    itemCaret,
    itemTypeIcon,
    itemActions,
    itemStats,
  },
  props: {
    parentGroup: {
      type: Object,
      required: false,
      default: () => ({}),
    },
    group: {
      type: Object,
      required: true,
    },
    action: {
      type: String,
      required: false,
      default: '',
    },
  },
  computed: {
    groupDomId() {
      return `group-${this.group.id}`;
    },
    rowClass() {
      return {
        'is-open': this.group.isOpen,
        'has-children': this.hasChildren,
        'has-description': this.group.description,
        'being-removed': this.group.isBeingRemoved,
      };
    },
    hasChildren() {
      return this.group.childrenCount > 0;
    },
    hasAvatar() {
      return this.group.avatarUrl !== null;
    },
    hasComplianceFramework() {
      return Boolean(this.group.complianceFramework?.name);
    },
    isGroup() {
      return this.group.type === 'group';
    },
    isGroupPendingRemoval() {
      return this.group.type === 'group' && this.group.pendingRemoval;
    },
    visibilityIcon() {
      return VISIBILITY_TYPE_ICON[this.group.visibility];
    },
    visibilityTooltip() {
      return GROUP_VISIBILITY_TYPE[this.group.visibility];
    },
    microdata() {
      return this.group.microdata || {};
    },
    complianceFramework() {
      return this.group.complianceFramework;
    },
    showActionsMenu() {
      return this.isGroup && (this.group.canEdit || this.group.canRemove || this.group.canLeave);
    },
  },
  methods: {
    onClickRowGroup(e) {
      const NO_EXPAND_CLS = 'no-expand';
      const targetClasses = e.target.classList;
      const parentElClasses = e.target.parentElement.classList;

      if (!(targetClasses.contains(NO_EXPAND_CLS) || parentElClasses.contains(NO_EXPAND_CLS))) {
        if (this.hasChildren) {
          eventHub.$emit(`${this.action}toggleChildren`, this.group);
        } else {
          visitUrl(this.group.relativePath);
        }
      }
    },
  },
  safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
  AVATAR_SHAPE_OPTION_RECT,
};
</script>

<template>
  <li
    :id="groupDomId"
    :class="rowClass"
    class="group-row"
    :itemprop="microdata.itemprop"
    :itemtype="microdata.itemtype"
    :itemscope="microdata.itemscope"
    @click.stop="onClickRowGroup"
  >
    <div
      :class="{ 'project-row-contents': !isGroup }"
      class="group-row-contents d-flex align-items-center py-2 pr-3"
    >
      <div class="folder-toggle-wrap gl-mr-2 d-flex align-items-center">
        <item-caret :is-group-open="group.isOpen" />
        <item-type-icon :item-type="group.type" />
      </div>
      <gl-loading-icon
        v-if="group.isChildrenLoading"
        size="lg"
        class="d-none d-sm-inline-flex flex-shrink-0 gl-mr-3"
      />
      <a
        :class="{ 'gl-sm-display-flex': !group.isChildrenLoading }"
        class="gl-display-none gl-text-decoration-none! gl-mr-3"
        :href="group.relativePath"
        :aria-label="group.name"
      >
        <gl-avatar
          :shape="$options.AVATAR_SHAPE_OPTION_RECT"
          :entity-name="group.name"
          :src="group.avatarUrl"
          :alt="group.name"
          :size="32"
          :itemprop="microdata.imageItemprop"
        />
      </a>
      <div class="group-text-container d-flex flex-fill align-items-center">
        <div class="group-text flex-grow-1 flex-shrink-1">
          <div
            class="gl-display-flex gl-align-items-center gl-flex-wrap title namespace-title gl-font-weight-bold gl-mr-3"
          >
            <a
              v-gl-tooltip.bottom
              data-testid="group-name"
              :href="group.relativePath"
              :title="group.fullName"
              class="no-expand gl-mr-3 gl-mt-3 gl-text-gray-900!"
              :itemprop="microdata.nameItemprop"
            >
              {{
                // ending bracket must be by closing tag to prevent
                // link hover text-decoration from over-extending
                group.name
              }}
            </a>
            <gl-icon
              v-gl-tooltip.hover.bottom
              class="gl-display-inline-flex gl-align-items-center gl-mr-3 gl-mt-3 gl-text-gray-500"
              :name="visibilityIcon"
              :title="visibilityTooltip"
              data-testid="group-visibility-icon"
            />
            <user-access-role-badge v-if="group.permission" class="gl-mt-3">
              {{ group.permission }}
            </user-access-role-badge>
            <compliance-framework-label
              v-if="hasComplianceFramework"
              class="gl-mt-3"
              :name="complianceFramework.name"
              :color="complianceFramework.color"
              :description="complianceFramework.description"
            />
          </div>
          <div v-if="group.description" class="description">
            <span
              v-safe-html:[$options.safeHtmlConfig]="group.description"
              :itemprop="microdata.descriptionItemprop"
              data-testid="group-description"
            >
            </span>
          </div>
        </div>
        <div v-if="isGroupPendingRemoval">
          <gl-badge variant="warning">{{ __('pending deletion') }}</gl-badge>
        </div>
        <div
          class="metadata gl-display-flex gl-flex-grow-1 gl-flex-shrink-0 gl-flex-wrap justify-content-md-between"
        >
          <item-stats
            :item="group"
            class="group-stats gl-mt-2 gl-display-none gl-md-display-flex gl-align-items-center"
          />
          <item-actions
            v-if="showActionsMenu"
            :group="group"
            :parent-group="parentGroup"
            :action="action"
          />
        </div>
      </div>
    </div>
    <group-folder
      v-if="group.isOpen && hasChildren"
      :parent-group="group"
      :groups="group.children"
      :action="action"
    />
  </li>
</template>
