<template>
  <div
    :class="[
      { 'pdf-export-container': isPdfRender },
      { 'is-reply': isReply },
      'tf-comment-container',
      'wt-comment-container'
    ]"
  >
    <ElAlert
      v-if="showSuccessMessage"
      data-test="comment success notification"
      show-icon
      :closable="false"
      :title="successMessage"
      type="success"
    />
    <TfBadge
      v-if="showLocalNewBadge"
      :class="{ 'indent': isReply }"
      size="small"
      status="success"
      value="new"
    />
    <p
      :class="[
        'sender-recipient',
        {
          'pdf-export-block': isPdfRender,
          'indent': isReply,
        }
      ]"
    >
      <strong>{{ userName }}</strong>
      <template v-if="commentRecipient">
        to <strong>{{ commentRecipient }}</strong>
      </template>
    </p>
    <p
      :class="[
        'date',
        {
          'pdf-export-block': isPdfRender,
          'indent': isReply
        }
      ]"
      v-text="$TF.DatesUtils.formatDateAndTime(comment.created_at)"
    />
    <div class="comment">
      <template v-for="(paragraphs, index) in commentParagraphs">
        <p
          v-for="(p, pIndex) in paragraphs"
          :key="`${index}-${pIndex}`"
          :class="{
            'no-break': paragraphs.length > 1 && pIndex !== paragraphs.length -1,
            'pdf-export-block': isPdfRender,
            'indent': isReply,
            'is-last': index === commentParagraphs.length -1 && pIndex === paragraphs.length -1
          }"
          v-text="p.trim()"
        />
      </template>
    </div>
    <TfButton
      v-show="!showCommentBox && showReplyButton"
      type="primary"
      icon="reply"
      size="text-icon"
      :class="{'indent': isReply}"
      @click="showCommentBox = true"
    >
      Reply
    </TfButton>
    <CommentInput
      v-show="showCommentBox && !isPdfRender"
      v-model="commentText"
      :application-namespace="applicationNamespace"
      :auto-save-timestamp="autoSaveTimestamp"
      :comment="comment"
      :inline-success="inlineSuccess"
      :parent-id="commentParentId"
      :project-id="projectId"
      :proposal-document-id="proposalDocumentId"
      :user-info="userInfo"
      @cancel="onCancel"
      @commentAdded="onCommentAdded"
    />
    <div v-show="orderedReplies.length">
      <comment
        v-for="(commentReply, index) in orderedReplies"
        :key="commentReply.id"
        :application-namespace="applicationNamespace"
        :broker="broker"
        :comment="commentReply"
        :documents="documents"
        :is-reply="true"
        :is-pdf-render="isPdfRender"
        :parent-id="commentParentId"
        :proposal-document-id="proposalDocumentId"
        :project-id="projectId"
        :show-reply-button="!index"
        :user-info="userInfo"
        @commentAdded="onCommentAdded"
      />
    </div>
  </div>
</template>

<script>
/**
 * The Comments component that includes the readonly and edit state of a comment.
 *
 * @vuedoc
 * @exports Comments/index
 * @category Components
 */
  export default {
    name: 'Comment',
    props: {
      applicationNamespace: {
        type: String,
        required: true,
        default: '',
      },
      broker: {
        type: Object,
        required: true,
        default: () => ({}),
      },
      comment: {
        type: Object,
        default: () => ({}),
      },
      documents: {
        type: Array,
        default: () => [],
      },
      inlineSuccess: {
        type: Boolean,
        default: true,
      },
      isReply: {
        type: Boolean,
        default: false,
      },
      isPdfRender: {
        type: Boolean,
        default: false,
      },
      parentId: {
        type: Number,
        default: null,
      },
      projectId: {
        type: [Number, String],
        default: '',
        required: true,
      },
      proposalDocumentId: {
        type: Number,
        default: null,
      },
      showNewBadge: {
        type: Boolean,
        default: true,
      },
      showReplyButton: {
        type: Boolean,
        default: true,
      },
      userInfo: {
        type: Object,
        required: true,
        default: () => ({
          firstName: '',
          lastName: '',
          organization: '',
          type: 'broker',
        }),
      },
    },

    data: () => ({
      autoSaveTimestamp: '',
      commentText: '',
      showSuccessMessage: false,
      showCommentBox: false,
    }),

    computed: {
      /**
       * Splits the comment content by `\n\n` into an array to use in the template.
       *
       * @returns {Array}
       */
      commentParagraphs() {
        return this.comment.content
          .split('\n\n')
          .map((p) => p.split('\n'));
      },

      /**
       * If this is a top level comment, we should reply to this comment.
       * If this is a reply, we should take the parentId prop
       *
       * @returns {string}
       */
      commentParentId() {
        return this.isReply ? this.parentId : this.comment.id;
      },

      /**
       * Evaluates recipient, userInfo and broker data to decide what to return in this.fullName.
       *
       * @returns {string}
       */
      commentRecipient() {
        const recipient = this.documents.find(
          (document) => document.id === this.comment.commentable_id,
        );
        let commentRecipient = null;

        if (recipient) {
          commentRecipient = this.broker.name;

          // IF: this.comment originated from a broker we know it's to the carrier of a document => the recipient's (carrier's) name
          // ELSE IF: this comment came from a carrier => assign broker name from this.userInfo.organization
          if (this.comment.user.broker.name) {
            commentRecipient = recipient.carrier.name;
          } else if (this.isBrokerUser) {
            commentRecipient = this.userInfo.organization;
          }
        }

        return commentRecipient;
      },

      /**
       * Determines if the user is a broker based on this.userInfo type.
       *
       * @returns {boolean}
       */
      isBrokerUser() {
        return this.userInfo.type === 'broker';
      },

      /**
       * Determines if the user is a carrier based on this.userInfo type.
       *
       * @returns {boolean}
       */
      isCarrierUser() {
        return this.userInfo.type === 'carrier';
      },

      /**
       * Evaluates broker and carrier data to decide what to return in this.fullName.
       *
       * @returns {boolean}
       */
      isSameOrganization() {
        const isBroker = this.isBrokerUser
          && this.userInfo.organization === this.comment.user.broker.name;
        const isCarrier = this.isCarrierUser
          && this.userInfo.organization === this.comment.user.carrier.name;

        return isCarrier || isBroker;
      },

      /**
       * Return organization name, if set, regardless of user type
       *
       * @returns {string}
       */
      organizationName() {
        const isBroker = this.comment.user.broker
          && this.comment.user.broker.name;
        const isCarrier = this.comment.user.carrier
          && this.comment.user.carrier.name;
        let organizationName = null;

        if (isCarrier) {
          organizationName = this.comment.user.carrier.name;
        }

        if (isBroker) {
          organizationName = this.comment.user.broker.name;
        }

        return organizationName;
      },
      /**
       * Return organization name, if set, regardless of user type
       *
       * @returns {Array}
       */
      orderedReplies() {
        return this.comment.replies
          // eslint-disable-next-line vue/no-side-effects-in-computed-properties
          ? this.$TF.Formatting.sortObjects(
            this.comment.replies,
            'created_at',
            'desc',
          )
          : [];
      },
      /**
       * Evaluates the comment and showNewBadge prop to decide to show the "new" badge.
       *
       * @returns {boolean}
       */
      showLocalNewBadge() {
        return this.comment.is_new && this.showNewBadge;
      },

      /**
       * Returns the success message based on user type.
       *
       * @returns {string}
       */
      successMessage() {
        return this.isBrokerUser
          ? 'Your comment has been sent to the carrier(s)'
          : 'Your comment has been sent to your broker.';
      },

      /**
       * Return organization name, if set, regardless of user type
       *
       * @returns {string}
       */
      userName() {
        const { user } = this.comment;
        let userName = `${user.first_name} ${user.last_name}`;

        if (!this.isSameOrganization) {
          userName = `${userName} at ${this.organizationName}`;
        }

        return userName;
      },
    },

    /*
  }
  * Check if we saved a comment in session storage that wasn't submitted and also sort any replies.
  * If this is a newly added comment, show the alert for 5 seconds.
  */
    created() {
      const savedComment = window.sessionStorage.getItem(`comment-${this.comment.id}`);

      if (savedComment) {
        const commentObject = JSON.parse(savedComment);
        this.autoSaveTimestamp = commentObject.timestamp;
        this.commentText = commentObject.message;
        this.showCommentBox = true;
      }

      if (this.comment.showSuccess) {
        this.showSuccessMessage = true;
        this.interval = setInterval(() => {
          this.showSuccessMessage = false;
        }, 5000);
      }
    },

    methods: {
      /**
       * Clear out the comment
       */
      clearData() {
        this.autoSaveTimestamp = '';
        this.commentText = '';
      },

      /**
       * Toggle the reply box for this comment
       */
      onCancel() {
        this.showCommentBox = false;
        this.clearData();
      },

      /**
       * Toggle the reply box for this comment and emit the reply to the parent
       *
       * @param {event} $event
       */
      onCommentAdded($event) {
        this.$emit('commentAdded', $event);
        this.showCommentBox = false;
        this.clearData();
      },
    },
  };
</script>

<style scoped lang="scss">
  @import 'src/assets/styles/variables';

  %hideOnPdf {
    .pdf-export-container & {
      display: none;
    }
  }

  .tf-comment-container,
  .wt-comment-container {
    padding: 15px 15px 15px 0;
    font-size: 14px;
    line-height: 20px;
    border-top: solid 1px $tf-extra-light-gray-1;

    &:first-child {
      border-top: 0;
    }

    &.is-reply:first-child {
      .el-alert + .name {
        padding-top: 14px;
      }
    }

    > .tf-badge {
      margin-bottom: 10px;
    }
  }

  .date {
    color: $tf-medium-gray;
    font-style: italic;
  }

  .el-alert {
    margin: 0 0 15px;

    @extend %hideOnPdf;
  }

  .alert-new.alert-simple {
    margin: 0;
    padding: 5px 10px;

    @extend %hideOnPdf;
  }

  .tf-button.icon-reply,
  .wt-button.icon-reply {
    margin-top: 12px;

    @extend %hideOnPdf;
  }

  // frustrating amount of specifity needed for these
  .indent,
  .alert-new.alert-simple.indent,
  .tf-button.indent,
  .wt-button.indent {
    margin-left: 35px;
  }

  p {
    margin: 0;
    line-height: 20px;

    .comment & {
      margin-bottom: 20px;

      &.no-break {
        margin-bottom: 0;
      }

      &:last-child {
        margin-bottom: 0;
      }
    }

    &.pdf-export-block {
      width: 530px;
      font-size: 12px;
      line-height: 16px;

      &.indent {
        width: 495px;
      }

      &.is-last {
        margin-bottom: 16px;
      }

      &.sender-recipient {
        padding-top: 16px;
        // Dashed lines currently break the UI (https://watchtower.atlassian.net/browse/BA-1563)
        // border-top: 2px $tf-light-gray dashed;
        border-top: 1px solid $tf-light-gray;

        .pdf-export-header + & {
          padding-top: 0;
          border-top: 0;
        }
      }
    }
  }
</style>
