<template>
  <div
    :class="{
      'message-input-audio': true,
      'message-input-audio-open': isAudioTouchBarShow,
    }"
  >
  <div class="audio-message-icon-container">
    <image
      v-if="isTikTok"
      :src="props.isInAudioMode ? keyboardIcon : audioIcon"
      :style="{width:'23px', height:'23px', padding: '2px'}"
      @click="switchAudio">
    </image>
    <Icon
      v-else
      class="audio-message-icon"
      :file="props.isInAudioMode ? keyboardIcon : audioIcon"
      :size="'23px'"
      :hotAreaSize="'3px'"
      @onClick="switchAudio"
    />
  </div>
    <view
      v-if="props.isInAudioMode"
      class="audio-input-touch-bar"
      @touchstart="handleTouchStart"
      @longpress="handleLongPress"
      @touchmove="handleTouchMove"
      @touchend="handleTouchEnd"
    >
      <span>{{ touchBarText }}</span>
      <view
        v-if="isRecording"
        class="record-container"
      >
        <view class="audio-bubble-blue">
          <image
            v-if="isTikTok"
            :src="willCancelBySlide ? audioBubbleRed : audioBubbleBlue"
            :style="{width: '160px', height: '74px'}">
          </image>
          <Icon
            v-else
            :file="willCancelBySlide ? audioBubbleRed : audioBubbleBlue"
            width="160px"
            height="74px"
          />
          <view class="loading">
            <view class="line1"></view>
            <view class="line3"></view>
            <view class="line2"></view>
            <view class="line4"></view>
            <view class="line1"></view>
            <view class="line3"></view>
            <view class="line4"></view>
            <view class="line1"></view>
            <view class="line2"></view>
            <view class="line1"></view>
            <view class="line4"></view>
            <!-- tiktok 小程序这里会换行... -->
            <view v-if="!isTikTok" class="line3"></view>
          </view>
        </view>
        <view class="modal-text">
          {{ modalText }}
        </view>
        <image
          v-if="isTikTok"
          class="audio-delete-icon-in-tt"
          :src="willCancelBySlide ? audioDeleteIcon : audioBeforeDeleteIcon">
        </image>
        <Icon
          v-if="!isTikTok"
          class="audio-delete-icon"
          :file="willCancelBySlide? audioDeleteIcon: audioBeforeDeleteIcon"
          width="54px"
          height="54px"
        />
        <image
          v-if="isTikTok"
          class="audio-record-icon-in-tt"
          :src="audioRecordIcon">
        </image>
        <Icon
          v-if="!isTikTok"
          class="audio-record-icon"
          width="16px"
          height="20px"
          :file="audioRecordIcon"
        />
        <view class="icon-container">
        </view>
      </view>
    </view>
  </div>
</template>
<script setup lang="ts">
import vue from '../../../adapter-vue';
import TUIChatEngine, {
  IConversationModel,
  StoreName,
  TUIChatService,
  TUIStore,
  TUITranslateService,
} from '../../../@aidesk/uikit-engine';
import Icon from '../../common/Icon.vue';
import audioIcon from '../../../assets/audio-blue.svg';
import keyboardIcon from '../../../assets/keyboard-icon.svg';
import {Toast, TOAST_TYPE} from '../../common/Toast/index-uniapp';
import {isEnabledMessageReadReceiptGlobal, throttle} from '../../../utils/utils';
import {InputDisplayType} from '../../../interface';
import audioRecordIcon from '../../../assets/msg-audio.svg';
import audioBeforeDeleteIcon from '../../../assets/audio-before-delete.svg';
import audioDeleteIcon from '../../../assets/audio-delete.svg';
import audioBubbleBlue from '../../../assets/audio-bubble-blue.svg';
import audioBubbleRed from '../../../assets/audio-bubble-red.svg';
import {isTikTok} from "../../../utils/env";
import Recorder from "js-audio-recorder";
import state from '../../../utils/state';
import Log from '../../../utils/logger';

const { ref, onMounted, onUnmounted, watch } = vue;

interface IProps {
  isInAudioMode: boolean;
}

interface IEmits {
  (e: 'changeDisplayType', type: InputDisplayType): void;
}

const emits = defineEmits<IEmits>();
const props = withDefaults(defineProps<IProps>(), {
  isInAudioMode: false,
});

let isManualCancelBySlide = false;
let recordTimer: number | undefined;
let firstTouchPageY: number = -1;
let isFingerTouchingScreen = false;
let isFirstAuthrizedRecord = false;

const recorder = ref(null);
const recordTime = ref(0);
let pressStartTime = 0;

const isRecording = ref(false);
const touchBarText = ref(TUITranslateService.t('TUIChat.按住说话'));
const modalText = ref(TUITranslateService.t('TUIChat.正在录音'));
const isAudioTouchBarShow = ref<boolean>(false);
const currentConversationID = ref('');
const willCancelBySlide = ref(false);
const recordTip = ref(TUITranslateService.t('TUIChat.松开发送'));

function switchAudio() {
  emits('changeDisplayType', props.isInAudioMode ? 'editor' : 'audio');
}

onMounted(() => {
  // Register events for the audio recording manager
  recorder.value = new Recorder({
    sampleBits: 16,
    sampleRate: 44100,
    numChannels: 1,
    compiling: false,
  });

  TUIStore.watch(StoreName.CONV, {
    currentConversationID: onCurrentConversationIDUpdated,
  });
});

onUnmounted(() => {
  TUIStore.unwatch(StoreName.CONV, {
    currentConversationID: onCurrentConversationIDUpdated,
  });
  if (recorder.value) {
    recorder.value.destroy().then(function() {
      recorder.value = null;
    });
  }
});

watch(recordTime, (newVal: number) => {
  if (newVal >= 50 && newVal < 60) {
    let tip = '';
    const currentLanguage = state.get('currentLanguage');
    if (currentLanguage === 'zh' || currentLanguage === 'zh_tw' || currentLanguage === 'ja') {
      tip = `${10 - newVal}${TUITranslateService.t('TUIChat.录音结束提醒')}`
    } else {
      tip = `${TUITranslateService.t('TUIChat.录音结束提醒')} ${10 - newVal}s`
    }
    recordTip.value = tip;
  } else if (newVal >= 60) {
    stopRecording();
  }
});

const startRecording = () => {
  if (isRecording.value) {
    return;
  }

  pressStartTime = Date.now();
  isRecording.value = true;
  willCancelBySlide.value = false;
  Recorder.getPermission().then(async() => {
    if (!isRecording.value) {
      return;
    }
    if (recordTimer !== undefined) {
      initRecorder();
    }
    recorder.value.start().then(() => {
      // updateRecordWave();
      recordTimer = setInterval(() => {
        recordTime.value = recordTime.value + 1;
      }, 1000);
    }, (error) => {
      Log.e(`Error in recording ${error.name} : ${error.message}`);
      let toastMessage = '';
      if (error.name === 'NotAllowedError') {
        toastMessage = TUITranslateService.t("TUIChat.请检查麦克风访问权限");
      } else {
        toastMessage = `${error.name} : ${error.message}`;
      }
      isRecording.value = false;
      initRecorder();
      showErrorToast(toastMessage);
    });
  }, (error) => {
    Log.e(`Error in mic permission ${error.name} : ${error.message}`);
    isRecording.value = false;
    initRecorder();
    showErrorToast(TUITranslateService.t("TUIChat.请检查麦克风访问权限"));
  });
};

const stopRecording = async () => {
  isRecording.value = false;
  willCancelBySlide.value = false;
  const duration = recordTime.value;
  initRecorder();
  const pressDuration = Date.now() - pressStartTime;
  if (pressDuration < 1000) {
    // 按压时间过短，还没开始录音就结束
    showErrorToast(TUITranslateService.t("TUIChat.按压时间过短，请按压超过1秒"));
  } else if (!willCancelBySlide.value && duration) {
    // 已经录音 && 没有取消录音
    if (duration <= 60) {
      let wavBlob = recorder.value.getWAVBlob();
      let tempFilePath = new File([wavBlob], `ai_desk_customer_uniapp_${Date.now()}.wav`, { type: "wav" });
      (tempFilePath as any).duration = duration * 1000;
      if (tempFilePath && duration <= 60) {
        try {
          TUIChatService.sendAudioMessage({
            to: currentConversationID.value.replace(TUIChatEngine.TYPES.CONV_C2C, ''),
            conversationType: TUIChatEngine.TYPES.CONV_C2C,
            payload: { file: tempFilePath },
            needReadReceipt: isEnabledMessageReadReceiptGlobal(),
          });
        } catch (error) {
          showErrorToast(`${TUITranslateService.t("TUIChat.发送语音消息失败")}: ${error}`);
        }
      }
    }
  }
};

function onCurrentConversationIDUpdated(conversation: IConversationModel) {
  currentConversationID.value = conversation;
}

async function initRecorder() {
  clearInterval(recordTimer);
  recordTimer = undefined;
  recordTime.value = 0;
  await recorder.value.stop();
  touchBarText.value = TUITranslateService.t('TUIChat.按住说话');
  modalText.value = '';
}

function handleTouchStart() {
  if (isFingerTouchingScreen) {
    // Compatibility: Ignore the recording generated by the user's first authorization on the APP.
    isFirstAuthrizedRecord = true;
    pressStartTime = Date.now();
  }
}

function handleLongPress() {
  isFingerTouchingScreen = true;
  startRecording();
}

const handleTouchMove = throttle(function (e) {
  if (isRecording.value) {
    const pageY = e.changedTouches[e.changedTouches.length - 1].pageY;
    if (firstTouchPageY < 0) {
      firstTouchPageY = pageY;
    }
    const offset = (firstTouchPageY as number) - pageY;
    if (offset > 110) {
      touchBarText.value = TUITranslateService.t('TUIChat.松手取消');
      modalText.value = TUITranslateService.t('TUIChat.松手取消');
      isManualCancelBySlide = true;
      willCancelBySlide.value = true;
    } else if (offset > 50) {
      touchBarText.value = TUITranslateService.t('TUIChat.松开发送');
      modalText.value = TUITranslateService.t('TUIChat.松开发送');
      // modalText.value = '继续上滑可取消';
      isManualCancelBySlide = false;
      willCancelBySlide.value = false;
    } else {
      // touchBarText.value = '抬起发送';
      touchBarText.value = TUITranslateService.t('TUIChat.松开发送');
      modalText.value = TUITranslateService.t('TUIChat.正在录音');
      // modalText.value = '正在录音';
      isManualCancelBySlide = false;
      willCancelBySlide.value = false;
    }
  }
}, 100);

function handleTouchEnd() {
  isFingerTouchingScreen = false;
  stopRecording();
}

function showErrorToast(message: string) {
  Toast({
    message,
    type: TOAST_TYPE.ERROR,
    duration: 2000,
  });
}
</script>

<style lang="scss" scoped>
@import "../style/common";

@keyframes voiceBar {
  from,
  10% {
    height: 10rpx;
  }
  to,
  90% {
    height: 50rpx;
  }
}

.message-input-audio {
  display: flex;
  flex-direction: row;
  align-items: center;

  .audio-message-icon-container{
    background-color: #fff;
    padding: 3px;
    margin-right: 10px;
    border-radius: 10px;
  }

  .audio-message-icon {
  }

  .audio-input-touch-bar {
    height: 39px;
    flex: 1;
    border-radius: 10px 0 0 10px;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    background-color: #fff;

    .record-container{
      height:60vh;
      width: 100vw;
      position:fixed;
      overflow: hidden;
      right: 0;
      bottom: 0;
      background: linear-gradient(to top, rgba(255, 255, 255, 1) 70%, rgba(255, 255, 255, 0));
      .audio-record-icon {
        position: absolute;
        bottom: 50px;
        left: 50%;
        transform: translateX(-50%);
        z-index: 2;
      }
      .audio-record-icon-in-tt {
        position: absolute;
        bottom: 50px;
        left: 50%;
        transform: translateX(-50%);
        z-index: 2;
        width: 16px;
        height: 20px;
      }
      .audio-delete-icon {
        position: absolute;
        bottom: 32%;
        left: 50%;
        transform: translateX(-50%);
        z-index: 2;
      }
      .audio-delete-icon-in-tt {
        position: absolute;
        bottom: 32%;
        left: 50%;
        transform: translateX(-50%);
        z-index: 2;
        width: 54px;
        height: 54px;
      }
      .icon-container {
        position: absolute;
        bottom: -183%;
        left: -70%;
        width: 950px;
        height: 950px;
        border-radius: 50%;
        background: linear-gradient(180deg, #E8EDF3 -1.18%, #FBFBFB 4.94%);
        box-shadow: 0px -7.5px 5px 0px rgba(218, 224, 232, 0.15);
      }
      .modal-text {
        position: absolute;
        top: 43%;
        left: 50%;
        transform: translateX(-50%);
        color: #4E5461;

      }
      .audio-bubble-blue {
        position: absolute;
        top: 20%;
        left: 50%;
        transform: translateX(-50%);
        .loading {
          position: absolute;
          top: 35rpx;
          left: 20rpx;
          width: 100%;
        }
        .loading > view {
          display: inline-block;
          vertical-align: middle;
          width: 8rpx;
          background-color: #fff;
          margin-right: 16rpx;
          border-radius: 50rpx;
        }
        .line1 {
          animation: voiceBar 0.6s infinite ease-in-out alternate;
        }
        .line2 {
          animation: voiceBar 0.4s infinite ease-in-out alternate;
        }
        .line3 {
          animation: voiceBar 0.5s infinite ease-in-out alternate;
        }
        .line4 {
          animation: voiceBar 0.3s infinite ease-in-out alternate;
        }
      }
    }

    .record-modal {
      height: 300rpx;
      width: 60vw;
      background-color: rgba(0, 0, 0, 0.8);
      position: fixed;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      z-index: 9999;
      border-radius: 24rpx;
      display: flex;
      flex-direction: column;
      overflow: hidden;

      .red-mask {
        position: absolute;
        inset: 0;
        background-color: rgba(#ff3e48, 0.5);
        opacity: 0;
        transition: opacity 10ms linear;
        z-index: 1;
      }

      .moving-slider {
        margin: 10vw;
        width: 40rpx;
        height: 16rpx;
        border-radius: 4rpx;
        background-color: #006fff;
        animation: loading 1s ease-in-out infinite alternate;
        z-index: 2;
      }

      .float-element {
        position: relative;
        z-index: 2;
      }
    }

    @keyframes loading {
      0% {
        transform: translate(0, 0);
      }

      100% {
        transform: translate(30vw, 0);
        background-color: #f5634a;
        width: 40px;
      }
    }

    .modal-title {
      text-align: center;
      color: #fff;
    }
  }

  &-open {
    flex: 1;
  }
}
</style>
