<!--
  Program: Board
  Author: SDL
  Brief: Post List
-->
<template>
  <div class="ui--content-wrapper">
    <sdl-breadcrumb></sdl-breadcrumb>
    <!-- SEARCH Area -->
    <!-- Processing according to the search area condition -->
    <div class="ui--search-container clearfix" v-if="boardInfo.searchConditionUsed || boardInfo.searchClassificationUsed || boardInfo.searchDateUsed">
      <div class="col-10 float-start">
        <div class="row">
          <div class="col-8" v-if="boardInfo.searchConditionUsed">
            <!-- form -->
            <div class="row">
              <label class="col-3 col-form-label text-end">{{ $t('sdl.common.label.searchCondition') }}</label>
              <div class="col-9">
                <div class="input-group">
                  <select class="form-select" style="width: 40%" v-model="searchCondition">
                    <option value="postTitle">{{ $t('sdl.common.label.title') }}</option>
                    <option value="postDetail">{{ $t('sdl.common.label.contents') }}</option>
                    <option value="postKeyword">{{ $t('sdl.common.label.title_contents') }}</option>
                  </select>
                  <input class="form-control" style="width: 60%" type="text" v-model="searchKeyword" @keydown.enter="getPostList()" />
                </div>
              </div>
            </div>
          </div>
          <div class="col-4" v-if="boardInfo.searchClassificationUsed">
            <!-- form -->
            <div class="row">
              <label class="col-4 col-form-label text-end">{{ $t('sdl.board.label.classification') }}</label>
              <div class="col-8">
                <!-- dropdown -->
                <select class="form-select" v-model="classificationId">
                  <option value="">{{ $t('sdl.common.label.all') }}</option>
                  <option v-for="item in boardInfo.classifications" :value="item.classificationId" :key="item.classificationId">
                    {{ item.classificationName }}
                  </option>
                </select>
              </div>
            </div>
          </div>
          <div class="col-6" v-else-if="boardInfo.searchDateUsed">
            <div class="row">
              <label class="col-2 col-form-label text-end">{{ $t('sdl.common.label.period') }}</label>
              <div class="col-10 form-inline">
                <sdl-datepicker v-model="searchPeriod" :period="searchPeriod"></sdl-datepicker>
              </div>
            </div>
          </div>
        </div>
        <div class="row mt-2" v-if="boardInfo.searchClassificationUsed && boardInfo.searchDateUsed">
          <div class="col-12">
            <!-- form -->
            <div class="row">
              <label class="col-2 col-form-label text-end">{{ $t('sdl.common.label.period') }}</label>
              <div class="col-10 form-inline">
                <sdl-datepicker v-model="searchPeriod" :period="searchPeriod"></sdl-datepicker>
              </div>
            </div>
          </div>
        </div>
        <!-- //row1 -->
      </div>
      <!-- search button -->
      <div class="col-2 float-end text-end">
        <button class="btn btn-primary btn-search" type="submit" @click="getPostList()">
          {{ $t('sdl.common.label.search') }}
        </button>
      </div>
    </div>
    <!-- LIST Header & buttons -->
    <div class="ui--list-heading clearfix">
      <span class="ui--text-total"> <strong>Total</strong> {{ $filters.numberFormat(records) }} </span>
      <div class="float-end">
        <!-- TODO: v-if="!boardInfo.noticePopupUsed"-->
        <button class="btn btn-primary btn-sm" type="button" @click="moveRegistPage()" v-authorization="'execute'">
          {{ $t('sdl.common.label.register') }}
        </button>
      </div>
    </div>
    <!-- TABLE / CARD style branch according to board type -->
    <!-- BASIC TYPE-->
    <template v-if="boardInfo.boardType === 'BASIC'">
      <table class="table table-bordered ui--table">
        <colgroup>
          <col v-for="item in usedColumns" :key="item.postMappColumn" :style="`width:${item.columnWidth}%;`" />
        </colgroup>
        <thead>
          <tr>
            <th v-for="item in usedColumns" :key="item.postMappColumn" scope="col">
              {{ $t(item.columnLabelCode || '') }}
            </th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="post in postList" v-show="post.hierarchyLevel <= 1 || post.show" :key="post.isNotice ? `${post.postId}_notice` : post.postId" class="cursor-pointer" :class="{ 'bg-light': post.isNotice }" @click="moveViewPage(post)">
            <td v-for="column in usedColumns" :class="getColumnClass(post, column.postMappColumn)" :key="column.columnSequence">
              <div v-if="column.postMappColumn === 'POST_TITLE'" class="text-truncate">
                <i class="bi bi-arrow-return-right flex-shrink-0" v-if="post.hierarchyLevel > 1">
                  <template v-for="(val, idx) in post.levelArr" :key="val">
                    <span v-if="idx > 0">&nbsp;</span>
                  </template>
                </i>
                {{ post[columnInfo[column.postMappColumn].name] }}
                <i v-if="post.attachExistsYn" class="bi bi-paperclip"></i>
                <i v-if="post.imageAttachExistsYn" class="bi bi-image"></i>
              </div>
              <template v-else-if="column.postMappColumn === 'NOTICE_LABEL'">
                <span v-if="post.isNotice" class="badge ui--status-primary">{{ $t('sdl.board.label.notice') }}</span>
              </template>
              <template v-else>
                {{ getFormattedValue(post, columnInfo[column.postMappColumn].name) }}
              </template>
              <button v-if="column.postMappColumn === 'POST_TITLE' && post.existReply" type="button" class="btn btn-checkbox btn-replay" @click.stop="toggleReply(post)">
                {{ $t('sdl.board.label.reply') }} {{ getReplyCount(post.postId) }}
                <i class="bi" :class="`bi-chevron-${post.fold}`"></i>
              </button>
            </td>
          </tr>
        </tbody>
      </table>
    </template>
    <!-- // BASIC TYPE-->
    <!-- PICTURE TYPE-->
    <template v-if="boardInfo.boardType === 'PICTURE'">
      <div class="ui--card-columns" v-for="(row, idx) in postList" :key="idx">
        <div class="card" v-for="post in row" :key="post.postId">
          <template v-if="post.postTitle">
            <div class="card-img">
              <img :ref="post.defaultImageFileId" src="" alt="Picture Board Image" />
            </div>
            <div class="card-body">
              <p class="d-flex">
                <span>
                  <small class="me-1">
                    By<a class="ms-1" href="javascript:void(0)">{{ post.regrName }}</a>
                  </small>
                </span>
                <span class="ms-auto">
                  <small>{{ $filters.dateFormat(post.regDate) }}</small>
                </span>
              </p>
              <h4 v-show="post.postTitle">
                <a href="javascript:void(0)" @click="moveViewPage(post)"> {{ post.classificationName ? `[${post.classificationName}] ` : '' }}{{ post.postTitle }} </a>
              </h4>
            </div>
          </template>
          <template v-else>
            <div class="card-img"></div>
            <div class="card-body">
              <p class="d-flex">
                <span>
                  <small class="me-1">
                    <a class="ms-1" href="javascript:void(0)"></a>
                  </small>
                </span>
                <span class="ms-auto">
                  <small></small>
                </span>
              </p>
              <h4>&nbsp;</h4>
            </div>
          </template>
        </div>
      </div>
    </template>
    <!-- // PICTURE TYPE-->

    <!-- Pagination Area-->
    <sdl-pagination v-show="listLoad" :current-page="currentPage" :total-rows="records" :per-page="this.boardInfo.pageSize" @change="movePage" align="center" />
    <!--  // Pagination Area-->
  </div>
</template>

<script>
import axios from 'axios';
import _ from 'lodash';
import { SDLUtil, DateUtil, StringUtil } from '@/utils';
import StoreParams from '@/mixin/StoreParams';

export default {
  mixins: [StoreParams],
  data() {
    return {
      listLoad: false,
      urlPath: _.replace(this.$route.path, `${this.$CONTEXT}/`, ''),
      roleType: '',
      boardId: '',
      boardInfo: {},
      searchCondition: 'postTitle',
      searchKeyword: '',
      searchPeriod: {},
      classificationId: '',
      noticePostList: [],
      tempPostList: [],
      postList: [],
      selectedPostId: '',
      records: 0, // total number of data
      currentPage: 1, // current page number
      pageSize: 10, // Number of lists per page
      // column information
      columnInfo: {
        NOTICE_LABEL: { name: 'noticeLabel', label: '', align: 'center' },
        CLASSIFICATION_NAME: { name: 'classificationName', align: 'center' },
        POST_TITLE: { name: 'postTitle', align: '' },
        NOTICE_POPUP_START_DATE: { name: 'noticePopupStartDate', align: 'center' },
        NOTICE_POPUP_END_DATE: { name: 'noticePopupEndDate', align: 'center' },
        REGR_NAME: { name: 'regrName', align: 'left' },
        REG_DATE: { name: 'regDate', align: 'center' },
        HIT_COUNT: { name: 'hitCount', align: 'center' },
      },
    };
  },
  computed: {
    // Column list with enabled
    usedColumns() {
      if (this.boardInfo.columns) {
        return this.boardInfo.columns.filter(column => column.used);
      }
      return [];
    },
  },
  methods: {
    /**
     * param:
     * return:
     * exception:
     * description : Initialize Page
     */
    init() {
      this.boardId = this.urlPath.split('/')[1] || '';
      this.roleType = this.urlPath.split('/')[2] || '';
      this.getBoardInfo();
    },
    /**
     * param:
     * return:
     * exception:
     * description : Retrieving Notice Popup
     */
    async getNoticePopupList() {
      SDLUtil.showLoadingBar(true);
      await axios
        .get(`${SDLUtil.API_URL}/boards/${this.boardId}/notice-popup-posts`)
        .then(({ data }) => {
          data.forEach(notice => {
            window.open(`/noticePopup/${this.boardId}/${notice.postId}`, 'popup', 'width=500,height=500');
          });
          SDLUtil.showLoadingBar(false);
        })
        .catch(err => {
          SDLUtil.showLoadingBar(false);
          SDLUtil.errorAlert(err);
        });
    },
    /**
     * param:
     * return:
     * exception:
     * description : Retrieving board information
     */
    async getBoardInfo() {
      SDLUtil.showLoadingBar(true);
      await axios
        .get(`${SDLUtil.API_URL}/boards/${this.boardId}`)
        .then(({ data }) => {
          this.boardInfo = data;
          SDLUtil.showLoadingBar(false);
        })
        .catch(err => {
          SDLUtil.showLoadingBar(false);
          SDLUtil.errorAlert(err);
        });
      this.initSearchInfo();
      SDLUtil.showLoadingBar(true);
      await axios
        .get(`${SDLUtil.API_URL}/boards/${this.boardId}/notice-label-posts`)
        .then(({ data }) => {
          this.noticePostList = data.map(post => {
            post.isNotice = true;
            return post;
          });
          SDLUtil.showLoadingBar(false);
        })
        .catch(err => {
          SDLUtil.showLoadingBar(false);
          SDLUtil.errorAlert(err);
        });
      this.getPostList();
    },
    /**
     * param:
     * return:
     * exception:
     * description : Search Information Initialization
     */
    initSearchInfo() {
      // period information initialization
      const storeParams = this.getStoreParameter();
      if (storeParams) {
        this.searchPeriod = { startDate: storeParams.startDate, endDate: storeParams.endDate };
        this.searchCondition = this.boardInfo.searchConditionUsed ? storeParams.searchCondition : null;
        this.searchKeyword = this.boardInfo.searchConditionUsed ? storeParams.searchKeyword : null;
        this.classificationId = this.boardInfo.searchClassificationUsed ? storeParams.classificationId : null;
      } else {
        this.searchPeriod.startDate = DateUtil.subDate(1, 'M');
        this.searchPeriod.endDate = DateUtil.now();
      }
    },
    /**
     * param: pageIndex -> Int (default: 1)
     * return:
     * exception:
     * description :Retrieving Post List
     */
    getPostList(pageIndex = 1) {
      this.listLoad = false;
      // Configure parameters according to bulletin board setting information
      let params = {
        pageIndex,
        boardId: this.boardId,
        pageSize: this.boardInfo.pageSize,
        searchCondition: this.searchCondition,
        searchKeyword: this.searchKeyword.trim(),
        classificationId: this.boardInfo.searchClassificationUsed ? this.classificationId : null,
      };
      // Add parameters depending on whether to search the date
      if (this.boardInfo.searchDateUsed) {
        // Change to date format standard at API request ('YYYY-MM-DD')
        const searchPeriod = DateUtil.stdFormat(this.searchPeriod);
        params = { ...params, ...searchPeriod };
      }
      // Remove null from parameter items
      params = _.omit(params, _.isNull);
      this.setStoreParameter(params);
      SDLUtil.showLoadingBar(true);
      axios
        .get(`${SDLUtil.API_URL}/boards/${this.boardId}/posts-with-paging?${StringUtil.queryStringfy(params)}`)
        .then(({ data }) => {
          if (_.eq(this.boardInfo.boardType, 'BASIC')) this.convertBasicList(data.rows);
          else this.convertPictureList(data.rows);
          this.currentPage = data.currentPage;
          this.records = data.records;
          SDLUtil.showLoadingBar(false);
          this.listLoad = true;
        })
        .catch(err => {
          SDLUtil.showLoadingBar(false);
          SDLUtil.errorAlert(err);
        });
    },
    /**
     * param: list -> Array
     * return:
     * exception:
     * description : Change the list of structures to a one-dimensional array - BASIC TYPE
     */
    convertBasicList(list) {
      this.tempPostList = _.cloneDeep(this.noticePostList);
      list.forEach(post => {
        post.fold = 'down';
        if (post.replyPosts.length > 0) post.existReply = true;
        this.addBasicList(post, post.postId);
      });
      this.postList = this.tempPostList;
    },
    /**
     * param: post -> Object
     * param: rootPostId -> String
     * return:
     * exception:
     * description : add post - BASIC TYPE
     */
    addBasicList(post, rootPostId) {
      const tempPost = _.omit(post, 'replyPosts');
      if (post.hierarchyLevel > 1) {
        tempPost.levelArr = new Array(post.hierarchyLevel);
        tempPost.rootPostId = rootPostId;
      } else tempPost.show = false;
      this.tempPostList.push(tempPost);
      post.replyPosts.forEach(child => {
        this.addBasicList(child, rootPostId);
      });
    },
    /**
     * param: list -> Array
     * return:
     * exception:
     * description : Change to an array of four post groups - PICTURE TYPE
     */
    convertPictureList(list) {
      this.postList = [];
      let rowGroup = [];
      list.forEach((post, idx) => {
        rowGroup.push(post);
        if (rowGroup.length === 4 || _.eq(idx, list.length - 1)) {
          while (rowGroup.length < 4) {
            rowGroup.push({});
          }
          this.postList.push(rowGroup);
          rowGroup = [];
        }
      });
      // Image type board > Load image attachment
      this.postList.forEach(row => {
        row.forEach(async post => {
          SDLUtil.showLoadingBar(true);
          if (post.postTitle) {
            await this.getImageContent(post.defaultImageFileId).then(blob => {
              this.$refs[post.defaultImageFileId][0].src = window.URL.createObjectURL(blob);
            });
          }
          SDLUtil.showLoadingBar(false);
        });
      });
    },
    /**
     * param: fileId -> String
     * return:
     * exception:
     * description : Image attachment load
     */
    getImageContent(fileId) {
      return new Promise((resolve, reject) => {
        axios({
          url: `${SDLUtil.API_URL}/resource/attachments/file-download/${fileId}?downloadType=${this.boardId}_IMAGE`,
          responseType: 'arraybuffer',
          method: 'get',
        })
          .then(response => {
            const blob = new Blob([response.data], { type: response.headers['content-type'] });
            return resolve(blob);
          })
          .catch(error => reject(error.message));
      });
    },
    /**
     * param: post -> Object
     * param: colKey -> String
     * return: String
     * exception:
     * description : column class specification
     */
    getColumnClass(post, colKey) {
      if (_.eq(colKey, 'POST_TITLE')) {
        return `board-title${_.some(this.postList, ['rootPostId', post.postId]) ? ' title-reply' : ''}`;
      }
      return _.isEmpty(this.columnInfo[colKey].align) ? '' : `text-${this.columnInfo[colKey].align}`;
    },
    /**
     * param: post -> Object
     * param: colName -> String
     * return: String
     * exception:
     * description : Specify formatted value according to data format
     */
    getFormattedValue(post, colName) {
      if (_.eq(colName, 'regDate')) {
        return this.$filters.dateFormat(post[colName]);
      }
      if (_.eq(colName, 'hitCount')) {
        return this.$filters.numberFormat(post[colName] || 0);
      }
      return post[colName];
    },
    /**
     * param: postId -> String
     * return: Int
     * exception:
     * description : Number of replies in the post
     */
    getReplyCount(postId) {
      return this.postList.filter(post => _.eq(post.rootPostId, postId)).length;
    },
    /**
     * param: rootPost -> Object
     * return:
     * exception:
     * description : The answer to the post is fold / unfold
     */
    toggleReply(rootPost) {
      rootPost.fold = _.eq(rootPost.fold, 'up') ? 'down' : 'up';
      this.postList.map(post => {
        if (_.eq(post.rootPostId, rootPost.postId)) {
          post.show = !post.show;
        }
        return post;
      });
    },
    /**
     * param:
     * return:
     * exception:
     * description : Move post registration page
     */
    moveRegistPage() {
      this.$router.push(`${this.$CONTEXT}/board/${this.boardId}/${this.roleType}/regist`);
    },
    /**
     * param: post -> Object
     * return:
     * exception:
     * description : Move post Details Page
     */
    moveViewPage(post) {
      const viewType = post.isNotice ? 'notice' : 'default';
      this.$router.push(`${this.$CONTEXT}/board/${this.boardId}/${this.roleType}/view/${post.postId}/${viewType}`);
    },
    /**
     * param: pageIndex -> Int
     * return:
     * exception:
     * description : Pagination move
     */
    movePage(pageIndex) {
      this.getPostList(pageIndex);
    },
  },
  mounted() {
    this.$nextTick(() => {
      console.info('initialize Board List Page');
      this.init();
    });
  },
};
</script>
<style scoped></style>
