/*
 * https://github.com/morethanwords/tweb
 * Copyright (C) 2019-2021 Eduard Kuzmenko
 * https://github.com/morethanwords/tweb/blob/master/LICENSE
 */

import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManager";
import type ChatTopbar from "./topbar";
import rootScope from "../../lib/rootScope";
import appMediaPlaybackController, { AppMediaPlaybackController } from "../appMediaPlaybackController";
import DivAndCaption from "../divAndCaption";
import PinnedContainer from "./pinnedContainer";
import Chat from "./chat";
import cancelEvent from "../../helpers/dom/cancelEvent";
import { attachClickEvent } from "../../helpers/dom/clickEvent";
import replaceContent from "../../helpers/dom/replaceContent";
import PeerTitle from "../peerTitle";
import { i18n } from "../../lib/langPack";
import { formatFullSentTime } from "../../helpers/date";
import ButtonIcon from "../buttonIcon";
import { DocumentAttribute } from "../../layer";
import MediaProgressLine from "../mediaProgressLine";
import VolumeSelector from "../volumeSelector";
import wrapEmojiText from "../../lib/richTextProcessor/wrapEmojiText";
import { AppManagers } from "../../lib/appManagers/managers";

export default class ChatAudio extends PinnedContainer {
  private toggleEl: HTMLElement;
  private progressLine: MediaProgressLine;
  private volumeSelector: VolumeSelector;
  private fasterEl: HTMLElement;
  private repeatEl: HTMLButtonElement;

  constructor(protected topbar: ChatTopbar, protected chat: Chat, protected managers: AppManagers) {
    super({
      topbar, 
      chat, 
      listenerSetter: topbar.listenerSetter, 
      className: 'audio', 
      divAndCaption: new DivAndCaption(
        'pinned-audio', 
        (title: string | HTMLElement | DocumentFragment, subtitle: string | HTMLElement | DocumentFragment) => {
          replaceContent(this.divAndCaption.title, title);
          replaceContent(this.divAndCaption.subtitle, subtitle);
        }
      ), 
      onClose: () => {
        appMediaPlaybackController.stop();
      },
      floating: true
    });

    this.divAndCaption.border.remove();

    const prevEl = ButtonIcon('fast_rewind active', {noRipple: true});
    const nextEl = ButtonIcon('fast_forward active', {noRipple: true});

    const attachClick = (elem: HTMLElement, callback: () => void) => {
      attachClickEvent(elem, (e) => {
        cancelEvent(e);
        callback();
      }, {listenerSetter: this.topbar.listenerSetter});
    };

    attachClick(prevEl, () => {
      appMediaPlaybackController.previous();
    });

    attachClick(nextEl, () => {
      appMediaPlaybackController.next();
    });

    this.toggleEl = ButtonIcon('', {noRipple: true});
    this.toggleEl.classList.add('active', 'pinned-audio-ico', 'tgico');
    attachClick(this.toggleEl, () => {
      appMediaPlaybackController.toggle();
    });
    this.wrapper.prepend(this.wrapper.firstElementChild, prevEl, this.toggleEl, nextEl);

    this.volumeSelector = new VolumeSelector(this.listenerSetter, true);
    const volumeProgressLineContainer = document.createElement('div');
    volumeProgressLineContainer.classList.add('progress-line-container');
    volumeProgressLineContainer.append(this.volumeSelector.container);
    const tunnel = document.createElement('div');
    tunnel.classList.add('pinned-audio-volume-tunnel');
    this.volumeSelector.btn.classList.add('pinned-audio-volume', 'active');
    this.volumeSelector.btn.prepend(tunnel);
    this.volumeSelector.btn.append(volumeProgressLineContainer);

    this.repeatEl = ButtonIcon('audio_repeat', {noRipple: true});
    attachClick(this.repeatEl, () => {
      const params = appMediaPlaybackController.getPlaybackParams();
      if(!params.round) {
        appMediaPlaybackController.round = true;
      } else if(params.loop) {
        appMediaPlaybackController.round = false;
        appMediaPlaybackController.loop = false;
      } else {
        appMediaPlaybackController.loop = !appMediaPlaybackController.loop;
      }
    });

    const fasterEl = this.fasterEl = ButtonIcon('playback_2x', {noRipple: true});
    attachClick(fasterEl, () => {
      appMediaPlaybackController.playbackRate = fasterEl.classList.contains('active') ? 1 : 1.75;
    });

    this.wrapperUtils.prepend(this.volumeSelector.btn, fasterEl, this.repeatEl);

    const progressWrapper = document.createElement('div');
    progressWrapper.classList.add('pinned-audio-progress-wrapper');

    this.progressLine = new MediaProgressLine(undefined, undefined, true, true);
    this.progressLine.container.classList.add('pinned-audio-progress');
    progressWrapper.append(this.progressLine.container);
    this.wrapper.insertBefore(progressWrapper, this.wrapperUtils);

    this.topbar.listenerSetter.add(appMediaPlaybackController)('play', this.onMediaPlay);
    this.topbar.listenerSetter.add(appMediaPlaybackController)('pause', this.onPause);
    this.topbar.listenerSetter.add(appMediaPlaybackController)('stop', this.onStop);
    this.topbar.listenerSetter.add(appMediaPlaybackController)('playbackParams', this.onPlaybackParams);

    const playingDetails = appMediaPlaybackController.getPlayingDetails();
    if(playingDetails) {
      this.onMediaPlay(playingDetails);
      this.onPlaybackParams(playingDetails.playbackParams);
    }
  }

  public destroy() {
    if(this.progressLine) {
      this.progressLine.removeListeners();
    }
  }

  private onPlaybackParams = (playbackParams: ReturnType<AppMediaPlaybackController['getPlaybackParams']>) => {
    this.fasterEl.classList.toggle('active', playbackParams.playbackRate > 1);

    this.repeatEl.classList.remove('tgico-audio_repeat', 'tgico-audio_repeat_single');
    this.repeatEl.classList.add(playbackParams.loop ? 'tgico-audio_repeat_single' : 'tgico-audio_repeat');
    this.repeatEl.classList.toggle('active', playbackParams.loop || playbackParams.round);
  };

  private onPause = () => {
    this.toggleEl.classList.remove('flip-icon');
  };

  private onStop = () => {
    this.toggle(true);
  };
  
  private onMediaPlay = ({doc, message, media, playbackParams}: ReturnType<AppMediaPlaybackController['getPlayingDetails']>) => {
    let title: string | HTMLElement | DocumentFragment, subtitle: string | HTMLElement | DocumentFragment;
    const isMusic = doc.type !== 'voice' && doc.type !== 'round';
    if(!isMusic) {
      title = new PeerTitle({peerId: message.fromId, fromName: message.fwd_from?.from_name}).element;

      //subtitle = 'Voice message';
      subtitle = formatFullSentTime(message.date);
    } else {
      const audioAttribute = doc.attributes.find((attr) => attr._ === 'documentAttributeAudio') as DocumentAttribute.documentAttributeAudio;
      title = wrapEmojiText(audioAttribute?.title ?? doc.file_name);
      subtitle = audioAttribute?.performer ? wrapEmojiText(audioAttribute.performer) : i18n('AudioUnknownArtist');
    }

    this.fasterEl.classList.toggle('hide', isMusic);
    this.repeatEl.classList.toggle('hide', !isMusic);

    this.onPlaybackParams(playbackParams);
    this.volumeSelector.setVolume();

    this.progressLine.setMedia(media);

    this.fill(title, subtitle, message);
    // this.toggleEl.classList.add('flip-icon');
    this.toggleEl.classList.toggle('flip-icon', !media.paused);
    this.toggle(false);
  };
}
