<template>
  <div ref="container" class="p-file-card" :style="{ height: containerH }">
    <VCard v-bind="cardAttrs" class="p-file-card__content">
      <div class="p-file-card__content-header">
        <!-- Favorite -->
        <div v-if="!hideFavorite" class="favorite-icon" @click="emit('on-click-favorite')">
          <VIcon size="21" :class="[isFavorite ? 'fas' : 'far', `fa-${favoriteIcon}`]" />
        </div>

        <VSpacer />
        <!-- New -->
        <div v-if="isNew" class="new-icon">
          <slot name="new" :newText="newText">
            <VChip v-bind="newChipAttrs" class="p-file-card__new-label">{{ newText }}</VChip>
          </slot>
        </div>
      </div>

      <!-- Image -->
      <VImg v-bind="imageAttrs" class="p-file-card__content-image" @click="emit('on-click-image')" />

      <div class="p-file-card__content-footer">
        <!-- Date -->
        <div class="file-date">
          {{ date }}
        </div>
        <VSpacer />

        <!-- Actions -->
        <div v-if="showFileOptions" class="p-file-card__actions">
          <slot name="actions">
            <VMenu v-bind="fileOptionsMenuAttrs">
              <template #activator="{ on }">
                <VIcon v-bind="fileOptionsIconAttrs" class="p-file-card__actions-icon" v-on="on">
                  {{ fileOptionsIcon }}
                </VIcon>
              </template>
              <VList v-bind="listAttrs">
                <VListItem
                  v-for="(item, i) in defaultedFileOptionsItems"
                  :key="i"
                  class="p-file-card__list-item"
                  @click="item.click"
                >
                  <VListItemIcon>
                    <VIcon v-text="item.icon" />
                  </VListItemIcon>
                  <VListItemContent>
                    <VListItemTitle v-text="item.text" />
                  </VListItemContent>
                </VListItem>
              </VList>
            </VMenu>
          </slot>
        </div>
      </div>
    </VCard>
    <slot name="body">
      <!-- File name -->
      <div class="p-file-card__file-name">{{ body }}</div>
      <!-- Keywords -->
      <slot name="keywords">
        <div v-if="keywords.length > 0">
          <span class="p-file-card__keywords">
            {{ keywords }}
          </span>
        </div>
      </slot>
    </slot>
  </div>
</template>

<script>
/* eslint-disable vue/no-deprecated-props-default-this */
import { computed, defineComponent, onBeforeUnmount, onMounted, reactive, toRefs } from '@vue/composition-api'

/**
 * Pitcher File Card component
 * @inherits v-card
 */
export default defineComponent({
  name: 'PFileCard',
  props: {
    body: {
      type: String,
      default: '',
    },
    favoriteIcon: {
      type: String,
      default: 'star',
    },
    hideFavorite: {
      type: Boolean,
      default: false,
    },
    imgUrl: String,
    date: String,
    keywords: {
      type: String,
      default: '',
    },
    isFavorite: Boolean,
    isNew: Boolean,
    showFileOptions: {
      type: Boolean,
      default: true,
    },
    downloadText: {
      type: String,
      default: 'Download',
    },
    shareText: {
      type: String,
      default: 'Share',
    },
    newText: {
      type: String,
      default: 'New',
    },
    height: {
      type: [String, Number],
      default: 295,
    },
    fileOptionsItems: {
      type: Array,
      required: false,
    },
    fileOptionsIcon: {
      type: String,
      default: 'fas fa-ellipsis-h',
    },
    fileOptionsIconProps: {
      type: Object,
      default: () => ({ color: 'grey', small: true }),
    },
    fileOptionsMenuProps: {
      type: Object,
      default: () => ({}),
    },
    listProps: {
      type: Object,
      default: () => ({ dense: true }),
    },
    newChipProps: {
      type: Object,
      default: () => ({
        color: 'red darken-1',
        label: true,
        'text-color': 'white',
        small: true,
      }),
    },
    imageProps: {
      type: Object,
      default: () => ({ contain: true }),
    },
  },
  emits: ['on-click-download', 'on-click-share', 'on-click-favorite', 'on-click-image'],
  setup(props, ctx) {
    const state = reactive({
      containerH: `${parseInt(props.height)}px`,
    })

    const defaultedFileOptionsItems = computed(() => {
      if (props.fileOptionsItems) return props.fileOptionsItems

      return [
        {
          text: props.downloadText,
          icon: 'fas fa-download',
          click: () => ctx.emit('on-click-download'),
        },
        {
          text: props.shareText,
          icon: 'fas fa-share-alt',
          click: () => ctx.emit('on-click-share'),
        },
      ]
    })

    const listAttrs = computed(() => props.listProps)

    const fileOptionsMenuAttrs = computed(() => props.fileOptionsMenuProps)

    const cardAttrs = computed(() => ({
      height: `${Math.ceil(parseInt(props.height) * 0.71)}px`,
      ...ctx.attrs,
    }))

    const fileOptionsIconAttrs = computed(() => props.fileOptionsIconProps)

    const imageAttrs = computed(() => ({
      src: props.imgUrl,
      ...props.imageProps,
    }))

    const newChipAttrs = computed(() => props.newChipProps)

    const breakpoints = {
      xs: 340,
      sm: 540,
      md: 800,
      lg: 1280,
      xl: 1920,
      xxl: 2600,
    }

    const calculateWidth = () => {
      const container = ctx.refs.container
      const parentContainer = container.parentNode

      if (!parentContainer || !container) return

      const parentWidth = parentContainer?.getBoundingClientRect().width
      const cardIndex = Array.from(parentContainer.children).indexOf(container) + 1
      const marginRight = 16

      container.style.marginRight = '0px'

      const setWidth = (columnPerRow) => {
        const availableWidth = parentWidth - marginRight * (columnPerRow - 1)

        container.style.width = `${availableWidth / columnPerRow}px`
        container.style.marginRight = cardIndex % columnPerRow === 0 ? '0px' : `${marginRight}px`
      }

      if (parentWidth <= breakpoints.xs) {
        container.style.width = '100%'
      } else if (parentWidth > breakpoints.xs && parentWidth <= breakpoints.sm) {
        setWidth(3)
      } else if (parentWidth > breakpoints.sm && parentWidth <= breakpoints.md) {
        setWidth(4)
      } else if (parentWidth > breakpoints.md && parentWidth <= breakpoints.lg) {
        setWidth(5)
      } else if (parentWidth > breakpoints.lg && parentWidth <= breakpoints.xl) {
        setWidth(8)
      } else if (parentWidth > breakpoints.xl && parentWidth <= breakpoints.xxl) {
        setWidth(10)
      } else if (parentWidth > breakpoints.xxl) {
        setWidth(12)
      }
    }

    onMounted(() => {
      calculateWidth()
      addEventListener('resize', calculateWidth)
    })

    onBeforeUnmount(() => {
      removeEventListener('resize', calculateWidth)
    })

    return {
      ...toRefs(state),
      listAttrs,
      cardAttrs,
      fileOptionsMenuAttrs,
      fileOptionsIconAttrs,
      imageAttrs,
      newChipAttrs,
      defaultedFileOptionsItems,
      emit: ctx.emit,
    }
  },
})
</script>

<style lang="scss" scoped>
@import '../../styles/mixins.scss';

.p-file-card {
  font-size: 16px;
  will-change: width;

  &__file-name {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 500;
  }

  &__keywords {
    overflow: hidden;
    color: #a7a7a7;
    font-size: 14px;
    align-self: flex-end;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  &__content {
    padding: 10px;
    margin-bottom: 10px;
    display: flex;
    flex-direction: column;

    &-header {
      display: flex;
      align-items: center;

      .favorite-icon,
      .new-icon {
        cursor: pointer;
        // margin must be added through inner elements,
        // as if inner elements are not visible, it will avoid to add margin to the header
        margin-bottom: 10px;
      }
    }

    &-image {
      flex: 1;
      cursor: pointer;
    }

    &-footer {
      display: flex;
      align-items: center;
      margin-top: 10px;

      .file-date {
        font-size: 14px;
      }
    }
  }

  &__list-item {
    .v-list-item__icon {
      margin-right: 16px;
    }
  }

  &__actions {
    align-self: flex-end;

    &-icon {
      border-radius: 4px;
      border: 1px solid;
      padding: 4px;

      &:hover {
        background: rgba(0, 0, 0, 0.05);
      }

      &::after {
        opacity: 0 !important;
      }
    }
  }

  &__new-label {
    padding: 0.6em 0.6em;
    font-weight: 500;
  }
}
</style>
