import { PhotoHelper } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, DisplayUtil, FileUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit'
import { SaveUtils } from '../../../../utils/SaveUtils'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
import { RectCropView, RectPosition } from '../../../../view/RectCropView'
import { media } from '@kit.MediaKit'
import { MediaUtils } from '../../../../utils/MediaUtils'
import { MP4Parser } from '@ohos/mp4parser'
import { TipDialog } from '../../../../dialog/TipDialog'
import { avSessionManager } from '../../../../manager/AVSessionManager'

@Entry
@ComponentV2
struct ClipVideoPage {
  @Local uri?: string
  @Local currentTime: number = 0
  @Local durationTime: number = 0
  @Local isPlaying: boolean = false
  @Local isSuccess: boolean = false
  @Local playerSize: media.PixelMapParams = { width: 0, height: 0 }
  @Local currentIndex: number = 0

  private controller: VideoController = new VideoController()
  private rectArray : Array<string> = ['自由', '1:1', '4:3', '3:4', '16:9', '9:16']
  private videoSize: media.PixelMapParams = { width: 0, height: 0 }
  private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 }

  clipVideo() {
    LoadingDialog.show(this.getUIContext())
    this.isSuccess = false
    let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `kcsp_${systemDateTime.getTime()}.mp4`
    if (FileUtil.accessSync(cacheVideoPath)) {
      FileUtil.unlinkSync(cacheVideoPath)
    }

    let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
    // 复制文件到缓存目录下
    FileUtil.copyFileSync(file.fd, cacheVideoPath)

    let clipWidth: number = 0
    let clipHeight: number = 0
    if (this.currentIndex === 0) {
      clipWidth = (vp2px(this.rect.width * this.videoSize.width!!) / this.playerSize.width!!)
      clipHeight = (vp2px(this.rect.height * this.videoSize.height!!) / this.playerSize.height!!)
    } else {
      const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width!!
      let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width!! * ratio), height: Math.ceil(this.videoSize.height!! * ratio)}
      clipWidth = (this.playerSize.width!! * this.videoSize.width!!) / originPlayerSize.width!!
      clipHeight = (this.playerSize.height!! * this.videoSize.height!!) / originPlayerSize.height!!
    }

    let clipX: number = 0
    let clipY: number = 0
    if (this.currentIndex === 0) {
      clipX = (vp2px(this.rect.x) * this.videoSize.width!!) / this.playerSize.width!!
      clipY = (vp2px(this.rect.y) * this.videoSize.width!!) / this.playerSize.height!!
    } else {
      const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width!!
      let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width!! * ratio), height: Math.ceil(this.videoSize.height!! * ratio)}
      clipX = clipWidth === originPlayerSize.width ? 0 : (originPlayerSize.width!! - this.playerSize.width!!) / 2 * (this.videoSize.width!!) / originPlayerSize.width!!
      clipY = clipHeight === originPlayerSize.height ? 0 : (originPlayerSize.height!! - this.playerSize.height!!) / 2 * (this.videoSize.height!!) / originPlayerSize.height!!
    }

    let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `kcsp_${systemDateTime.getTime()}.mp4`
    let cmd = `ffmpeg -i ${cacheVideoPath} -vf \"crop=${Math.ceil(clipWidth)}:${Math.ceil(clipHeight)}:${Math.ceil(clipX)}:${Math.ceil(clipY)}\" -c:v h264 -pix_fmt yuv420p -y ${outputPath}`
    MP4Parser.ffmpegCmd(cmd, {
      callBackResult: (code: number) => {
        if (code === 0) {
          this.uri = FileUtil.getUriFromPath(outputPath)
          MediaUtils.getVideoSize(this.uri)
            .then((size) => {
              this.videoSize = size
              if (size.width && size.height) {
                const ratio = (DisplayUtil.getWidth() - 180) / size.width
                this.playerSize = {width: Math.ceil(size.width * ratio), height: Math.ceil(size.height * ratio)}
              }
            })
          this.isSuccess = true
          this.isPlaying = false
          ToastUtils.show('处理成功')
        } else {
          ToastUtils.show('处理失败')
        }
        LoadingDialog.dismiss()
      }
    })
  }

  setVideoRatio() {
    if (this.videoSize.width && this.videoSize.height) {
      const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width
      let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width * ratio), height: Math.ceil(this.videoSize.height * ratio)}

      if (originPlayerSize.width && originPlayerSize.height) {
        switch (this.currentIndex) {
          case 0: {
            this.playerSize = originPlayerSize
            break
          }

          case 1: {
            if (originPlayerSize.width >= originPlayerSize.height) {
              this.playerSize = {width: originPlayerSize.height, height: originPlayerSize.height}
            } else {
              this.playerSize = {width: originPlayerSize.width, height: originPlayerSize.width}
            }
            break
          }

          case 2: {
            if (originPlayerSize.width / originPlayerSize.height >= 4 / 3) {
              this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 3 * 4), height: originPlayerSize.height}
            } else {
              this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 4 * 3)}
            }
            break
          }

          case 3: {
            if (originPlayerSize.width / originPlayerSize.height <= 3 / 4) {
              this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 3 * 4)}
            } else {
              this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 4 * 3), height: originPlayerSize.height}
            }
            break
          }

          case 4: {
            if (originPlayerSize.width / originPlayerSize.height >= 16 / 9) {
              this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 9 * 16), height: originPlayerSize.height}
            } else {
              this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 16 * 9)}
            }
            break
          }

          case 5: {
            if (originPlayerSize.width / originPlayerSize.height <= 9 / 16) {
              this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 9 * 16)}
            } else {
              this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 16 * 9), height: originPlayerSize.height}
            }
            break
          }
        }
      }
    }
  }

  selectVideo() {
    PhotoHelper.selectEasy({
      MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE,
      maxSelectNumber: 1,
      isPhotoTakingSupported: false,
      isEditSupported: false,
      isOriginalSupported: false
    })
      .then((uris) => {
        if (uris.length != 0) {
          this.isSuccess = false
          this.uri = uris[0]
          this.currentIndex = 0

          MediaUtils.getVideoSize(this.uri)
            .then((size) => {
              this.videoSize = size
              if (size.width && size.height) {
                const ratio = (DisplayUtil.getWidth() - 180) / size.width
                this.playerSize = {width: Math.ceil(size.width * ratio), height: Math.ceil(size.height * ratio)}
              }
            })
        }
      })
  }

  showDownloadDialog() {
    DownloadDialog.show(this.getUIContext(), {
      status: DownloadStatus.COMPLETED,
      totalSize: 0,
      progress: 0,
      totalCount: 1,
      index: 0,
      callback: {
        confirm: () => {
          AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0)
          this.getUIContext().getRouter().back()
        }
      }
    })
  }

  formatTime(time: number): string {
    let minute: number = 0
    let second: number = 0
    if (time > 60) {
      minute = Math.trunc(time / 60)
      second = time % 60
      if (minute < 10) {
        if (second < 10) {
          return `0${minute}:0${second}`
        } else {
          return `0${minute}:${second}`
        }
      } else {
        if (second < 10) {
          return `${minute}:0${second}`
        } else {
          return `${minute}:${second}`
        }
      }
    } else {
      second = time
      if (second < 10) {
        return `00:0${second}`
      } else {
        return `00:${second}`
      }
    }
  }

  onBackPress(): boolean | void {
    if (this.isSuccess) {
      TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存，是否确定退出？', callback: {
        confirm: () => {
          this.getUIContext().getRouter().back()
        }
      }})
      return true
    }
    return false
  }

  build() {
    Column() {
      TitleBar({ title: '视频裁剪' })

      Column() {
        Row() {
          Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium)
          Text('（仅支持mp4格式）').fontColor($r('app.color.color_50ffffff')).fontSize(12)
        }.alignSelf(ItemAlign.Start)

        RelativeContainer() {
          Stack() {
            Image($r('app.media.ic_add_video')).width(44).height(44)
          }
          .width(140)
          .height(140)
          .borderRadius(10)
          .backgroundColor($r('app.color.color_333333'))
          .alignRules({
            start: { anchor: '__container__', align: HorizontalAlign.Start },
            top: { anchor: '__container__', align: VerticalAlign.Top },
            end: { anchor: '__container__', align: HorizontalAlign.End },
            bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
          })
          .onClick(() => {
            this.selectVideo()
          })
        }
        .height(220)
        .margin({ top: 12 })
        .borderRadius(8)
        .backgroundColor($r('app.color.color_222222'))
      }.margin({ left: 16, top: 16, right: 16 })
      .visibility(this.uri ? Visibility.None : Visibility.Visible)

      Column() {
        RelativeContainer() {
          Video({
            src: this.uri, // 设置视频源
            controller: this.controller, //设置视频控制器，可以控制视频的播放状态
            posterOptions: { showFirstFrame: true }
          })
            .id('video')
            .width(this.playerSize ? px2vp(this.playerSize.width) : '100%')
            .height(this.playerSize ? px2vp(this.playerSize.height) : '100%')
            .backgroundColor($r('app.color.window_background'))
            .controls(false) // 设置是否显示默认控制条
            .autoPlay(false) // 设置是否自动播放
            .loop(false) // 设置是否循环播放
            .objectFit(ImageFit.Cover) // 设置视频填充模式
            .alignRules({
              left: { anchor: '__container__', align: HorizontalAlign.Start },
              top: { anchor: '__container__', align: VerticalAlign.Top },
              right: { anchor: '__container__', align: HorizontalAlign.End },
              bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
            })
            .onPrepared((event) => {
              if (event) {
                this.durationTime = event.duration
              }
            })
            .onUpdate((event) => {
              if (event) {
                this.currentTime = event.time
              }
            })
            .onStart(() => {
              this.isPlaying = true
            })
            .onPause(() => {
              this.isPlaying = false
              avSessionManager.deactivate()
            })
            .onStop(() => {
              this.isPlaying = false
              avSessionManager.deactivate()
            })
            .onFinish(() => {
              this.isPlaying = false
              avSessionManager.deactivate()
            })
            .onError(() => {
              this.isPlaying = false
              avSessionManager.deactivate()
            })
            .onDisAppear(() => {
              avSessionManager.deactivate()
            })

          Image($r('app.media.ic_play_video'))
            .width(50)
            .height(50)
            .visibility(this.isPlaying ? Visibility.None : Visibility.Visible)
            .onClick(async () => {
              await avSessionManager.activate()
              this.controller.start()
            })
            .alignRules({
              left: { anchor: 'video', align: HorizontalAlign.Start },
              top: { anchor: 'video', align: VerticalAlign.Top },
              right: { anchor: 'video', align: HorizontalAlign.End },
              bottom: { anchor: 'video', align: VerticalAlign.Bottom }
            })

          Row() {
            Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play'))
              .width(20)
              .height(20)
              .margin({ right: 20 })
              .onClick(async () => {
                if (this.isPlaying) {
                  this.controller.pause()
                } else {
                  await avSessionManager.activate()
                  this.controller.start()
                }
              })
            Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12)
            Slider({
              value: this.currentTime,
              min: 0,
              max: this.durationTime
            })
              .blockColor(Color.White)
              .trackColor($r('app.color.color_60ffffff'))
              .onChange((value: number, mode: SliderChangeMode) => {
                this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处
              })
              .layoutWeight(1)
            Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12)
          }
          .opacity(0.8)
          .width(this.playerSize ? px2vp(this.playerSize.width) : "100%")
          .alignRules({
            left: { anchor: 'video', align: HorizontalAlign.Start },
            right: { anchor: 'video', align: HorizontalAlign.End },
            bottom: { anchor: 'video', align: VerticalAlign.Bottom }
          })

          RectCropView({
            onRectChange: (rect) => {
              this.rect = rect
            }
          })
            .width(this.playerSize ? px2vp(this.playerSize.width) : '100%')
            .height(this.playerSize ? px2vp(this.playerSize.height) : '100%')
            .alignRules({
              left: { anchor: 'video', align: HorizontalAlign.Start },
              top: { anchor: 'video', align: VerticalAlign.Top },
              right: { anchor: 'video', align: HorizontalAlign.End },
              bottom: { anchor: 'video', align: VerticalAlign.Bottom }
            })
            .visibility(this.uri && this.currentIndex === 0 && !this.isSuccess ? Visibility.Visible : Visibility.None)
        }
        .layoutWeight(1)

        Grid() {
          ForEach(this.rectArray, (item: string, index) => {
            GridItem() {
              Text(item).width(50).height(50)
                .textAlign(TextAlign.Center)
                .fontColor(Color.White)
                .borderRadius(4)
                .borderWidth(1.5)
                .borderColor(this.currentIndex === index ? '#D33952' : Color.Transparent)
                .backgroundColor('#282828')
                .onClick(() => {
                  this.currentIndex = index
                  this.controller.stop()
                  this.setVideoRatio()
                })
            }
            .width('100%')
          })
        }
        .height(50)
        .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')
        .layoutDirection(GridDirection.Row)
        .visibility(this.uri && !this.isSuccess ? Visibility.Visible : Visibility.None)

        Row() {
          Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff'))
            .fontSize(17)
            .margin({ left: 16 })
            .onClick(() => {
              this.controller.stop()
              if (this.isSuccess) {
                this.selectVideo()
              } else {
                this.getUIContext().getRouter().back()
              }
            })
          Blank().layoutWeight(1)
          Text(this.isSuccess ? '保存' : '确定')
            .fontColor($r("app.color.color_466afd"))
            .fontSize(17)
            .margin({ right: 16 })
            .onClick(() => {
              this.controller.stop()
              if (this.isSuccess) {
                SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
                  .then((saved) => {
                    if (saved) {
                      this.uri = undefined
                      this.showDownloadDialog()
                    } else {
                      ToastUtils.show('保存失败')
                    }
                  })
                  .catch((e: BusinessError) => {
                    ToastUtils.show('保存失败：' + e.message)
                  })

              } else {
                this.clipVideo()
              }
            })
        }
        .margin({ top: 20, bottom: 30 })
      }
      .layoutWeight(1)
      .visibility(this.uri ? Visibility.Visible : Visibility.None)
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.window_background'))
  }
}