<template lang="pug">
  div(v-intersect.once='onIntersect')
    v-textarea#discussion-new(
      outlined
      flat
      placeholder='Write a new comment...'
      auto-grow
      dense
      rows='3'
      hide-details
      v-model='newcomment'
      color='blue-grey darken-2'
      :background-color='$vuetify.theme.dark ? `grey darken-5` : `white`'
      v-if='permissions.write'
    )
    v-row.mt-2(dense, v-if='!isAuthenticated && permissions.write')
      v-col(cols='12', lg='6')
        v-text-field(
          outlined
          color='blue-grey darken-2'
          :background-color='$vuetify.theme.dark ? `grey darken-5` : `white`'
          placeholder='Your Name'
          hide-details
          dense
          autocomplete='name'
          v-model='guestName'
        )
      v-col(cols='12', lg='6')
        v-text-field(
          outlined
          color='blue-grey darken-2'
          :background-color='$vuetify.theme.dark ? `grey darken-5` : `white`'
          placeholder='Your Email Address'
          hide-details
          type='email'
          dense
          autocomplete='email'
          v-model='guestEmail'
        )
    .d-flex.align-center.pt-3(v-if='permissions.write')
      v-icon.mr-1(color='blue-grey') mdi-language-markdown-outline
      .caption.blue-grey--text Markdown Format
      v-spacer
      .caption.mr-3(v-if='isAuthenticated') Posting as #[strong {{userDisplayName}}]
      v-btn(
        dark
        color='blue-grey darken-2'
        @click='postComment'
        depressed
        )
        v-icon(left) mdi-comment
        span.text-none Post Comment
    v-divider.mt-3(v-if='permissions.write')
    .pa-5.d-flex.align-center.justify-center(v-if='isLoading && !hasLoadedOnce')
      v-progress-circular(
        indeterminate
        size='20'
        width='1'
        color='blue-grey'
      )
      .caption.blue-grey--text.pl-3: em Loading comments...
    v-timeline(
      dense
      v-else-if='comments && comments.length > 0'
      )
      v-timeline-item.comments-post(
        color='pink darken-4'
        large
        v-for='cm of comments'
        :key='`comment-` + cm.id'
        :id='`comment-post-id-` + cm.id'
        )
        template(v-slot:icon)
          v-avatar(color='blue-grey')
            //- v-img(src='http://i.pravatar.cc/64')
            span.white--text.title {{cm.initials}}
        v-card.elevation-1
          v-card-text
            .comments-post-actions(v-if='permissions.manage && !isBusy')
              v-icon.mr-3(small, @click='editComment(cm)') mdi-pencil
              v-icon(small, @click='deleteCommentConfirm(cm)') mdi-delete
            .comments-post-name.caption: strong {{cm.authorName}}
            .comments-post-date.overline.grey--text {{cm.createdAt | moment('from') }} #[em(v-if='cm.createdAt !== cm.updatedAt') - modified {{cm.updatedAt | moment('from') }}]
            .comments-post-content.mt-3(v-html='cm.render')
    .pt-5.text-center.body-2.blue-grey--text(v-else-if='permissions.write') Be the first to comment.
    .text-center.body-2.blue-grey--text(v-else) No comments yet.

    v-dialog(v-model='deleteCommentDialogShown', max-width='500')
      v-card
        .dialog-header.is-red Confirm Delete
        v-card-text.pt-5
          span Are you sure you want to permanently delete this comment?
          .caption: strong This action cannot be undone!
        v-card-chin
          v-spacer
          v-btn(text, @click='deleteCommentDialogShown = false') {{$t('common:actions.cancel')}}
          v-btn(color='red', dark, @click='deleteComment') {{$t('common:actions.delete')}}
</template>

<script>
import gql from 'graphql-tag'
import { get } from 'vuex-pathify'
import validate from 'validate.js'
import _ from 'lodash'

export default {
  data () {
    return {
      newcomment: '',
      isLoading: true,
      hasLoadedOnce: false,
      comments: [],
      guestName: '',
      guestEmail: '',
      commentToDelete: {},
      deleteCommentDialogShown: false,
      isBusy: false,
      scrollOpts: {
        duration: 1500,
        offset: 0,
        easing: 'easeInOutCubic'
      }
    }
  },
  computed: {
    pageId: get('page/id'),
    permissions: get('page/commentsPermissions'),
    isAuthenticated: get('user/authenticated'),
    userDisplayName: get('user/name')
  },
  methods: {
    onIntersect (entries, observer, isIntersecting) {
      if (isIntersecting) {
        this.fetch()
      }
    },
    async fetch () {
      this.isLoading = true
      const results = await this.$apollo.query({
        query: gql`
          query ($locale: String!, $path: String!) {
            comments {
              list(locale: $locale, path: $path) {
                id
                render
                authorName
                createdAt
                updatedAt
              }
            }
          }
        `,
        variables: {
          locale: this.$store.get('page/locale'),
          path: this.$store.get('page/path')
        },
        fetchPolicy: 'network-only'
      })
      this.comments = _.get(results, 'data.comments.list', []).map(c => {
        const nameParts = c.authorName.toUpperCase().split(' ')
        let initials = _.head(nameParts).charAt(0)
        if (nameParts.length > 1) {
          initials += _.last(nameParts).charAt(0)
        }
        c.initials = initials
        return c
      })
      this.isLoading = false
      this.hasLoadedOnce = true
    },
    /**
     * Post New Comment
     */
    async postComment () {
      let rules = {
        comment: {
          presence: {
            allowEmpty: false
          },
          length: {
            minimum: 2
          }
        }
      }
      if (!this.isAuthenticated && this.permissions.write) {
        rules.name = {
          presence: {
            allowEmpty: false
          },
          length: {
            minimum: 2,
            maximum: 255
          }
        }
        rules.email = {
          presence: {
            allowEmpty: false
          },
          email: true
        }
      }
      const validationResults = validate({
        comment: this.newcomment,
        name: this.guestName,
        email: this.guestEmail
      }, rules, { format: 'flat' })

      if (validationResults) {
        this.$store.commit('showNotification', {
          style: 'red',
          message: validationResults[0],
          icon: 'alert'
        })
        return
      }

      const resp = await this.$apollo.mutate({
        mutation: gql`
          mutation (
            $pageId: Int!
            $replyTo: Int
            $content: String!
            $guestName: String
            $guestEmail: String
          ) {
            comments {
              create (
                pageId: $pageId
                replyTo: $replyTo
                content: $content
                guestName: $guestName
                guestEmail: $guestEmail
              ) {
                responseResult {
                  succeeded
                  errorCode
                  slug
                  message
                }
                id
              }
            }
          }
        `,
        variables: {
          pageId: this.pageId,
          replyTo: 0,
          content: this.newcomment,
          guestName: this.guestName,
          guestEmail: this.guestEmail
        }
      })

      if (_.get(resp, 'data.comments.create.responseResult.succeeded', false)) {
        this.$store.commit('showNotification', {
          style: 'success',
          message: 'New comment posted successfully.',
          icon: 'check'
        })

        this.newcomment = ''
        await this.fetch()
        this.$nextTick(() => {
          this.$vuetify.goTo(`#comment-post-id-${_.get(resp, 'data.comments.create.id', 0)}`, this.scrollOpts)
        })
      } else {
        this.$store.commit('showNotification', {
          style: 'red',
          message: _.get(resp, 'data.comments.create.responseResult.message', 'An unexpected error occured.'),
          icon: 'alert'
        })
      }
    },
    async editComment (cm) {

    },
    deleteCommentConfirm (cm) {
      this.commentToDelete = cm
      this.deleteCommentDialogShown = true
    },
    /**
     * Delete Comment
     */
    async deleteComment () {
      this.$store.commit(`loadingStart`, 'comments-delete')
      this.isBusy = true
      this.deleteCommentDialogShown = false

      const resp = await this.$apollo.mutate({
        mutation: gql`
          mutation (
            $id: Int!
          ) {
            comments {
              delete (
                id: $id
              ) {
                responseResult {
                  succeeded
                  errorCode
                  slug
                  message
                }
              }
            }
          }
        `,
        variables: {
          id: this.commentToDelete.id
        }
      })

      if (_.get(resp, 'data.comments.delete.responseResult.succeeded', false)) {
        this.$store.commit('showNotification', {
          style: 'success',
          message: 'Comment was deleted successfully.',
          icon: 'check'
        })

        this.comments = _.reject(this.comments, ['id', this.commentToDelete.id])
      } else {
        this.$store.commit('showNotification', {
          style: 'red',
          message: _.get(resp, 'data.comments.delete.responseResult.message', 'An unexpected error occured.'),
          icon: 'alert'
        })
      }
      this.isBusy = false
      this.$store.commit(`loadingStop`, 'comments-delete')
    }
  }
}
</script>

<style lang="scss">
.comments-post {
  position: relative;

  &:hover {
    .comments-post-actions {
      opacity: 1;
    }
  }

  &-actions {
    position: absolute;
    top: 16px;
    right: 16px;
    opacity: 0;
    transition: opacity .4s ease;
  }

  &-content {
    > p:first-child {
      padding-top: 0;
    }

    p {
      padding-top: 1rem;
      margin-bottom: 0;
    }

    img {
      max-width: 100%;
    }

    code {
      background-color: rgba(mc('pink', '500'), .1);
      box-shadow: none;
    }

    pre > code {
      margin-top: 1rem;
      padding: 12px;
      background-color: #111;
      box-shadow: none;
      border-radius: 5px;
      width: 100%;
      color: #FFF;
      font-weight: 400;
      font-size: .85rem;
      font-family: Roboto Mono, monospace;
    }
  }
}
</style>
