<script>
  import $ from 'jquery';
  import { mapGetters, mapActions } from 'vuex';
  import { getLocationHash } from '../../lib/utils/url_utility';
  import Flash from '../../flash';
  import store from '../stores/';
  import * as constants from '../constants';
  import noteableNote from './noteable_note.vue';
  import noteableDiscussion from './noteable_discussion.vue';
  import systemNote from '../../vue_shared/components/notes/system_note.vue';
  import commentForm from './comment_form.vue';
  import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
  import placeholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
  import loadingIcon from '../../vue_shared/components/loading_icon.vue';
  import skeletonLoadingContainer from '../../vue_shared/components/notes/skeleton_note.vue';

  export default {
    name: 'NotesApp',
    components: {
      noteableNote,
      noteableDiscussion,
      systemNote,
      commentForm,
      loadingIcon,
      placeholderNote,
      placeholderSystemNote,
    },
    props: {
      noteableData: {
        type: Object,
        required: true,
      },
      notesData: {
        type: Object,
        required: true,
      },
      userData: {
        type: Object,
        required: false,
        default: () => ({}),
      },
    },
    store,
    data() {
      return {
        isLoading: true,
      };
    },
    computed: {
      ...mapGetters([
        'notes',
        'getNotesDataByProp',
        'discussionCount',
      ]),
      noteableType() {
        // FIXME -- @fatihacet Get this from JSON data.
        const { ISSUE_NOTEABLE_TYPE, MERGE_REQUEST_NOTEABLE_TYPE } = constants;

        return this.noteableData.merge_params ? MERGE_REQUEST_NOTEABLE_TYPE : ISSUE_NOTEABLE_TYPE;
      },
      allNotes() {
        if (this.isLoading) {
          const totalNotes = parseInt(this.notesData.totalNotes, 10) || 0;

          return new Array(totalNotes).fill({
            isSkeletonNote: true,
          });
        }
        return this.notes;
      },
    },
    created() {
      this.setNotesData(this.notesData);
      this.setNoteableData(this.noteableData);
      this.setUserData(this.userData);
    },
    mounted() {
      this.fetchNotes();

      const parentElement = this.$el.parentElement;

      if (parentElement &&
        parentElement.classList.contains('js-vue-notes-event')) {
        parentElement.addEventListener('toggleAward', (event) => {
          const { awardName, noteId } = event.detail;
          this.actionToggleAward({ awardName, noteId });
        });
      }
      document.addEventListener('refreshVueNotes', this.fetchNotes);
    },
    beforeDestroy() {
      document.removeEventListener('refreshVueNotes', this.fetchNotes);
    },
    methods: {
      ...mapActions({
        actionFetchNotes: 'fetchNotes',
        poll: 'poll',
        actionToggleAward: 'toggleAward',
        scrollToNoteIfNeeded: 'scrollToNoteIfNeeded',
        setNotesData: 'setNotesData',
        setNoteableData: 'setNoteableData',
        setUserData: 'setUserData',
        setLastFetchedAt: 'setLastFetchedAt',
        setTargetNoteHash: 'setTargetNoteHash',
      }),
      getComponentName(note) {
        if (note.isSkeletonNote) {
          return skeletonLoadingContainer;
        }
        if (note.isPlaceholderNote) {
          if (note.placeholderType === constants.SYSTEM_NOTE) {
            return placeholderSystemNote;
          }
          return placeholderNote;
        } else if (note.individual_note) {
          return note.notes[0].system ? systemNote : noteableNote;
        }

        return noteableDiscussion;
      },
      getComponentData(note) {
        return note.individual_note ? note.notes[0] : note;
      },
      fetchNotes() {
        return this.actionFetchNotes(this.getNotesDataByProp('discussionsPath'))
          .then(() => this.initPolling())
          .then(() => {
            this.isLoading = false;
          })
          .then(() => this.$nextTick())
          .then(() => this.checkLocationHash())
          .catch(() => {
            this.isLoading = false;
            Flash('Something went wrong while fetching comments. Please try again.');
          });
      },
      initPolling() {
        if (this.isPollingInitialized) {
          return;
        }

        this.setLastFetchedAt(this.getNotesDataByProp('lastFetchedAt'));

        this.poll();
        this.isPollingInitialized = true;
      },
      checkLocationHash() {
        const hash = getLocationHash();
        const element = document.getElementById(hash);

        if (hash && element) {
          this.setTargetNoteHash(hash);
          this.scrollToNoteIfNeeded($(element));
        }
      },
    },
  };
</script>

<template>
  <div id="notes">
    <ul
      id="notes-list"
      class="notes main-notes-list timeline">

      <component
        v-for="note in allNotes"
        :is="getComponentName(note)"
        :note="getComponentData(note)"
        :key="note.id"
      />
    </ul>

    <comment-form
      :noteable-type="noteableType"
    />
  </div>
</template>
