<template>
  <div class="main">
    <template v-if="!!lianxi">
      <div class="header" ref="header">
        <div class="top-area">
          <div class="rate-area">
            <van-rate color="#ffd21e" :size="18" :readonly="readonly" v-model="state.rating.stars"/>
            <i class="rate-text">{{rating_text}}</i>
          </div>
        </div>
        <div class="text-area" v-if="lianxi?.text_question">
          {{lianxi.text_question}}
        </div>
        <div class="course-area" v-if="course_section">
          {{course_section.course_name}}({{course_section.section_name}})
          <span class="extra-span">
            <van-icon size="16" name="guide-o" color="#1989fa" @click="$router.push('/teacher/jihua/detail?id=' + params.jihua_id + '&qs=' + course_section.id)" />
            <score-show :icon="'video'" v-if="lianxi.video?.resource_url" :target="lianxi.video?.resource_url" :horizontal="true" :simple="true" :scores="lianxi.scores"></score-show>
            <i v-if="lianxi.video?.resource_url && lianxi.audio?.resource_url" class="fa-solid fa-slash backslash"></i>
            <score-show :icon="'audio'" v-if="lianxi.audio?.resource_url" :target="lianxi.audio?.resource_url" :horizontal="true" :simple="true" :scores="lianxi.scores"></score-show>
          </span>
        </div>
      </div>
      <div class="piyue" :style="{height: 'calc(100% - ' + header_height + ' - 1rem)'}">
        <div class="mark-area">
          <lianxi-pigai :disabled="disabled" :video_id="video_id" v-if="!!qupu" :replyable="true" :readonly="readonly" :qupu="qupu" :marks="state.marks"
                        :commentator="create_jihua_comment" @update="update($event)" @notify="notify_comment($event)" />
        </div>
        <div class="playing-area">
          <hty-video :id="video_id" :src="video"></hty-video>
        </div>
      </div>
      <div class="audio-area" v-if="has_audio">
        <strong>练习录音：</strong>
        <audio-play @click="play_question(lianxi)" :playing="playing === lianxi?.id"></audio-play>
      </div>
      <div class="footer">
        <van-badge :content="comments_count" color="#0dcaf0" :show-zero="false" max="99">
          <van-button @click="answer" type="primary" block size="small">留言回复</van-button>
        </van-badge>
        <van-button type="primary" block size="small" :disabled="!can_save" v-if="!readonly" @click="save">提交</van-button>
      </div>
    </template>
    <PiyueSkeleton v-else />
  </div>
  <van-action-sheet :lock-scroll="false" v-model:show="replying" title="留言回复" @closed="replying = false" :close-on-click-overlay="false" :closeable="!state.answer">
    <comments-sheet :disabled="disabled" :ref_id="lianxi?.piyue?.id" :qupu="qupu" :comment="state.answer" @reply="replyComment" @submit="saveComment" @remove="removeComment"></comments-sheet>
  </van-action-sheet>
</template>

<script lang="ts">
import {
  computed,
  defineComponent,
  reactive,
  ref,
  onBeforeUnmount,
  onBeforeMount,
  watch,
  nextTick
} from 'vue';
import {Button, Empty, Rate, Popover, Sticky, ActionSheet, Badge, Icon, showConfirmDialog, showLoadingToast, showNotify} from 'vant';
import LianxiPigai from "~/components/lianxi-pigai.vue";
import CommentBlock from '~/components/comment-block.vue';
import CommentsSheet from '~/components/comments-sheet.vue';
import useJihua from "~/store/jihua";
import useUser from '~/store/user';
import {
  Lianxi,
  Piyue,
  RatingTexts,
  Comment,
  CommentContent,
  CommentRefTypes,
  NotifyParam,
  NotifyTypes,
  HtyBaseRoles,
  RefResourceTypes,
  ResourceNote, PoolData, PickTargets, CourseSection,
  TimeUnits
} from "~/types";
import useAudio from "~/store/audio";
import {wxUtil} from "~/utils/wx";
import {useRouter} from "vue-router";
import AudioPlay from '~/components/audio-play.vue'
import AudioRecord from "~/components/audio-record.vue";
import HtyVideo from '~/components/hty-video.vue'
import ScoreShow from '~/components/score-show.vue'
import usePiyue from "~/store/piyue";
import usePool from "~/store/pool";
import useComment from "~/store/comment";
import {PiyueLockMinutes, uuid} from "~/utils";
import useTimer from "~/store/timer";
import PiyueSkeleton from '~/components/piyue-skeleton.vue'
import dayjs from "dayjs";

export interface PiyueState {
  rating: {
    stars: number, comment?: CommentContent
  },
  answer: Comment | null, marks: ResourceNote[]
}

export default defineComponent({
  name: 'teacher-piyue',
  components: {
    PiyueSkeleton,
    [Button.name]: Button,
    [Rate.name]: Rate,
    [LianxiPigai.name]: LianxiPigai,
    [CommentBlock.name]: CommentBlock,
    [Empty.name]: Empty,
    [AudioPlay.name]: AudioPlay,
    [Popover.name]: Popover,
    [Sticky.name]: Sticky,
    [Badge.name]: Badge,
    [HtyVideo.name]: HtyVideo,
    [AudioRecord.name]: AudioRecord,
    [ActionSheet.name]: ActionSheet,
    [CommentsSheet.name]: CommentsSheet,
    [Icon.name]: Icon,
    [ScoreShow.name]: ScoreShow
  },
  props: {
    params: {}
  },
  setup({params}: any) {
    wxUtil.init(['startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice']);
    const {store, create_jihua_piyue, create_jihua_comment, notify, read, check_tasks} = useJihua();
    const usingAudio = useAudio();
    const usingUser = useUser();
    const usingPool = usePool()
    const router = useRouter();
    const {prepare_piyue} = usePiyue();
    const {count_comments, get_comments} = useComment()
    const {startTimer, stopTimer} = useTimer()
    const video_id = uuid();
    const {setRemoteCache, getRemoteCache, delRemoteCache, clear} = usingPool

    const header = ref(null)
    const header_height = ref('1rem')
    const video = computed(() => store.current_lianxi?.video?.resource_url)

    const qupu = computed(() => {
      let lianxi_qupu = store.current_lianxi?.qupu;
      if (lianxi_qupu) return lianxi_qupu;
      let qs = store.current.course_sections.find(x => x.lianxis?.includes(store.current_lianxi));
      return (qs?.ref_resources || qs?.resources)?.find(r => r.resource_type === RefResourceTypes.Picture);
    })

    const course_section = computed(() => {
      return store.current.course_sections.find(x => x.lianxis?.includes(store.current_lianxi));
    })

    const lianxi = computed(() => store.current_lianxi);
    const replying = ref(false)

    const piyueing = ref<any>(null)

    const get_course_notes = () => {
      if (store.current_lianxi?.piyues?.length) {
        return store.current_lianxi?.piyues[0]?.resource_note_group?.resource_notes || []
      }
      return (usingPool.getKey("course_section") as CourseSection)?.resource_note_group?.resource_notes || []
    }

    const state = reactive<PiyueState>({
      rating: {
        stars: lianxi.value?.piyue?.rating?.stars || 0,
        comment: lianxi.value?.piyue?.rating?.comment
      },
      answer: null,
      marks: get_course_notes()
    });

    watch(() => store.current_lianxi, (value) => {
      if (value) {
        if (value.piyues) {
          state.rating = {
            stars: value.piyues[0]?.rating?.stars || 0,
            comment: value.piyues[0]?.rating?.comment
          };
        }
        state.answer = null;
        state.marks = get_course_notes()
      }
    })

    const rating_text = computed(() => state.rating.comment?.text || RatingTexts[state.rating.stars])

    const readonly = computed(() => !!(lianxi.value?.piyue?.id || piyueing.value))

    const show_text_question = ref(false)

    const notify_comment = ({comment_id, serial}: {comment_id: string, serial?: string}) => {
      let params: NotifyParam = {
        notify_type: NotifyTypes.TeacherCommentPiyue,
        hty_id: store.current.student_id,
        lianxi_id: store.current_lianxi?.id,
        jihua_id: store.current.id,
        comment_id, serial
      }
      notify(params, HtyBaseRoles.STUDENT)
    }

    const replyComment = (parent_id?: string) => {
      if (!state.answer) {
        state.answer = { parent_id, ref_type: CommentRefTypes.Piyue, content: {} as CommentContent} as Comment
      }
    }

    const saveComment = async () => {
      if (!lianxi.value?.piyue?.id) {
        replying.value = false;
      } else {
        let created = await create_jihua_comment({...(state.answer as Comment), ref_id: store.current_lianxi?.piyue?.id});
        if (created) {
          state.answer = null;
          notify_comment({comment_id: created.id})
        }
      }
    }

    const removeComment = () => {
      replying.value = false;
      state.answer = null;
    }

    const update = (data: ResourceNote[]) => {
      state.marks = data;
    }

    const playing = computed(() => usingAudio.store.target)
    const play_question = ({id, audio}: Lianxi) => {
      if (playing.value === id) {
        usingAudio.stop();
      } else {
        if (audio?.tasks?.vals) {
          let media_id = audio?.tasks?.vals[0]?.task_meta?.media_id;
          usingAudio.play({target: id, audio_url: audio?.resource_url, serverId: media_id})
        }
      }
    }

    onBeforeMount(async () => {
      if (params) {
        let { lianxi_id, jihua_id, from_tongzhi, comment_id } = params;
        let data: PoolData = {lianxi_id, jihua_id, business_type: PickTargets.JIHUA}
        if ((from_tongzhi || !store.current_lianxi) && lianxi_id && jihua_id) {
          await read(jihua_id, store.current.id !== jihua_id || from_tongzhi);
        }
        (store.current.course_sections || []).forEach(qs => {
          (qs.lianxis || []).forEach(lianxi => {
            if (lianxi.id === lianxi_id) {
              store.current_lianxi = lianxi;
              data.piyue_id = lianxi.piyue?.id;
              data.course_section = qs;
            }
          })
        })
        // 该lianxi可能已经被删除
        if (!store.current_lianxi) {
          showConfirmDialog({
            message: "该练习已被学生删除",
            cancelButtonText: "返回通知",
            confirmButtonText: "查看计划详情",
            showCancelButton: !!from_tongzhi
          }).then(() => {
            router.replace("/teacher/jihua/detail?id=" + jihua_id)
          }).catch(() => {
            router.back();
          })
          return;
        }
        usingPool.set(data)
        if (!data.piyue_id) {
          let payload = {
            union_id: usingUser.store.current.union_id,
            hty_id: usingUser.store.current.hty_id,
            real_name: usingUser.store.current.real_name
          }
          let key = "piyue_" + data.lianxi_id;
          let tmp = await getRemoteCache(key);
          if (tmp) {
            try {
              tmp = JSON.parse(tmp)
            } catch (e) {
              console.log('json parse failed...', e)
            }
            if (tmp.hty_id !== payload.hty_id) {
              piyueing.value = tmp;
              showNotify(tmp.real_name + "老师正在批阅该练习，您当前只能查看不可批阅！")
            } else {
              await setRemoteCache(key, payload, PiyueLockMinutes, TimeUnits.MINUTE)
            }
          } else {
            await setRemoteCache(key, payload, PiyueLockMinutes, TimeUnits.MINUTE)
          }
        }
        let prefix = store.current_lianxi?.id + "_" + usingUser.store.current.union_id
        let raw = await getRemoteCache(prefix + "_raw")
        console.log('raw...', raw)
        let submitted = await getRemoteCache(prefix + "_submit");
        console.log("submitted...", submitted)
        // new comment added to piyue show comments sheet
        if (comment_id) {
          let comments = get_comments(data.piyue_id);
          if(comments.some(c => c.id === comment_id)) {
            replying.value = true;
          }
        }
      }
      await nextTick(() => {
        let el = header.value as unknown as HTMLDivElement;
        header_height.value = el.offsetHeight + 'px';
      })
      usingUser.set_editing(true);
      if (store.current.id) {
        startTimer(() => store.current, check_tasks)
      }
    });


    onBeforeUnmount(() => {
      let data = usingPool.get();
      if (!piyueing.value) {
        // 自己批阅，清理锁
        let key = "piyue_" + (data?.lianxi_id || store.current_lianxi?.id);
        delRemoteCache(key)
      }
      store.current_lianxi = undefined
      clear();
      stopTimer()
    })

    const save = async () => {

      showLoadingToast({
        onClose: async () => {
          let raw = {
            lianxi_id: store.current_lianxi?.id,
            rating: state.rating, comments: []
          } as Piyue;
          let qupu = store.current_lianxi?.qupu;
          if (!qupu) {
            let course_section = store.current.course_sections.find(x => x.lianxis?.includes(store.current_lianxi));
            qupu = (course_section?.ref_resources || course_section?.resources)?.find(r => r.resource_type === RefResourceTypes.Picture);
          }
          let video = store.current_lianxi?.video;
          // todo: save audio position info
          let audio = store.current_lianxi?.audio;

          let redis_key = raw.lianxi_id + "_" + usingUser.store.current.union_id
          await setRemoteCache(redis_key + "_raw", {marks: state.marks, answer: state.answer})
          let piyue = await prepare_piyue(raw, state.marks, {qupu, video, audio}, state.answer as Comment);
          await setRemoteCache(redis_key + "_submit", piyue)

          console.log('data to submit...', piyue);
          let piyue_id = await create_jihua_piyue(piyue)
          if (piyue_id) {
            router.back();
          }
        }
      })
    }

    const can_save = computed(() => {
      if (!state.rating.stars) return false;
      if (state.marks.length > 0) return true;
      if (!state.answer) return false;
      let { content } = state.answer;
      return content?.text || content?.video?.resource_url || (content?.audio?.tasks?.vals && content?.audio?.tasks?.vals[0]?.task_meta?.media_id);
    })

    const has_audio = computed(() => store.current_lianxi?.audio)

    const comments_count = computed(() => {
      let id = store.current_lianxi?.piyue?.id;
      return id ? count_comments(id) : (state.answer ? 1 : 0)
    })

    const expired = computed(() => dayjs(store.current.end_date).valueOf() < dayjs().startOf('date').valueOf())


    const disabled = computed(() => {
      let user_role = usingUser.store.currentRole;
      return (user_role !== HtyBaseRoles.TEACHER)
    })

    const answer = () => {
      replying.value = true;
      if (!comments_count.value) {
        replyComment()
      }
    }

    return {
      video, qupu, readonly, update, replying, answer, course_section, expired,
      video_id, rating_text, can_save, header, header_height, has_audio, disabled,
      show_text_question, lianxi, play_question, notify_comment, create_jihua_comment,
      playing, save, state, replyComment, saveComment, removeComment, comments_count
    }
  },
})
</script>

<style scoped lang="less">
  .main {
    padding: 0;
    overflow: auto;
    position: relative;


    .header {
      padding: 0.16rem;
      background: #FFFFFF;
      box-shadow: 0 0 5px 6px #eeeeee;

      .top-area {
        display: flex;
        align-items: center;
        justify-content: flex-end;

        .rate-area {
          width: 2.4rem;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: space-between;

          .rate-text {
            font-size: 0.16rem;
            color: #9e9e9e;
          }
        }
      }

      .text-area, .course-area {
        border-top: 1px dashed #e5e5e5;
        font-size: 12px;
        color: #999999;
        width: 100%;
        padding-top: 0.12rem;
        background-clip: padding-box;
        border-radius: 0.125rem;
      }

      .course-area {
        color: #333;
        font-weight: bolder;
        text-align: center;
        display: flex;
        flex-direction: column;
        font-size: 0.2rem;
        .extra-span {
          display: inline-flex;
          align-items: baseline;
          justify-content: center;
          height: 16px;

          i.backslash {
            transform: rotateY(180deg);
            margin-left: 5px;
          }
        }
      }

    }

    .audio-area {
      display: flex;
      align-items: center;
      font-size: 0.28rem;
      justify-content: space-between;
      margin-top: 0.2rem;
      padding: 0 0.25rem;
      height: 0.6rem;

      .btn-info {
        border: none;
        margin: 0 0.06rem;

        &:before {
          background: #fff;
          border: none;
        }
      }

      .no-text {
        color: #9e9e9e;
        font-size: 0.24rem;
      }
    }

    .piyue {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      padding: 0.16rem 0;
      height: calc(100% - 2rem);
      align-content: center;

      .playing-area {
        height: 49%;
        width: 94%;
        margin: 0.16rem auto;
      }

      .mark-area {
        width: 94%;
        margin: auto;
        height: 49%;
      }

    }

    .footer {
      height: 1rem;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0.16rem;
      background: #FFFFFF;
      box-shadow: 0 0 5px 6px #eeeeee;

      .van-button, .van-badge__wrapper {
        width: 40%;

        .van-button {
          width: 100%;
        }
      }

      .no-text {
        width: 40%;
        color: #9e9e9e;
        font-size: 0.24rem;
        margin-left: 0.06rem;
      }
    }
  }

  .popover-text {
    padding: 0.16rem;
    font-size: 0.24rem;
  }
</style>
