// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import { assert } from 'chai';

import type { TargetedConversationChangedActionType } from '../../../state/ducks/conversations';
import {
  TARGETED_CONVERSATION_CHANGED,
  actions as conversationsActions,
} from '../../../state/ducks/conversations';
import { noopAction } from '../../../state/ducks/noop';

import type { StateType } from '../../../state/reducer';
import { reducer as rootReducer } from '../../../state/reducer';
import { actions, AudioPlayerContent } from '../../../state/ducks/audioPlayer';
import type { VoiceNoteAndConsecutiveForPlayback } from '../../../state/selectors/audioPlayer';

const { messageDeleted, messageChanged } = conversationsActions;

const MESSAGE_ID = 'message-id';

function voiceNoteDataForMessage(
  messageId: string
): VoiceNoteAndConsecutiveForPlayback {
  return {
    conversationId: 'convo',
    voiceNote: {
      id: messageId,
      type: 'outgoing',
      timestamp: 0,
      url: undefined,
      source: undefined,
      sourceServiceId: undefined,
      messageIdForLogging: messageId,
      isPlayed: false,
    },
    consecutiveVoiceNotes: [],
    previousMessageId: undefined,
    nextMessageTimestamp: undefined,
    playbackRate: 1,
  };
}

describe('both/state/ducks/audioPlayer', () => {
  const getEmptyRootState = (): StateType => {
    return rootReducer(undefined, noopAction());
  };

  const getInitializedState = (): StateType => {
    const state = getEmptyRootState();
    const updated = rootReducer(
      state,
      actions.loadVoiceNoteAudio({
        voiceNoteData: voiceNoteDataForMessage(MESSAGE_ID),
        position: 0,
        context: 'context',
        ourConversationId: 'convo',
        playbackRate: 1,
      })
    );

    const content = updated.audioPlayer.active?.content;

    assert.isTrue(content && AudioPlayerContent.isVoiceNote(content));

    if (content && AudioPlayerContent.isVoiceNote(content)) {
      assert.strictEqual(content.current.id, MESSAGE_ID);
      assert.strictEqual(content.context, 'context');
    }

    return updated;
  };

  describe('loadMessageAudio', () => {
    it("updates `active` in the audioPlayer's state", () => {
      const state = getEmptyRootState();
      assert.strictEqual(state.audioPlayer.active, undefined);

      const updated = rootReducer(
        state,
        actions.loadVoiceNoteAudio({
          voiceNoteData: voiceNoteDataForMessage('test'),
          position: 0,
          context: 'context',
          ourConversationId: 'convo',
          playbackRate: 1,
        })
      );

      const content = updated.audioPlayer.active?.content;
      assert.isTrue(content && AudioPlayerContent.isVoiceNote(content));

      if (content && AudioPlayerContent.isVoiceNote(content)) {
        assert.strictEqual(content.current.id, 'test');
        assert.strictEqual(content.context, 'context');
      }
    });
  });

  it('active is not changed when changing the conversation', () => {
    const state = getInitializedState();

    const action: TargetedConversationChangedActionType = {
      type: TARGETED_CONVERSATION_CHANGED,
      payload: { conversationId: 'any' },
    };
    const updated = rootReducer(state, action);

    const content = updated.audioPlayer.active?.content;
    assert.isTrue(content && AudioPlayerContent.isVoiceNote(content));

    if (content && AudioPlayerContent.isVoiceNote(content)) {
      assert.strictEqual(content.current.id, MESSAGE_ID);
    }
  });

  it('resets active.content when message was deleted', () => {
    const state = getInitializedState();

    const updated = rootReducer(
      state,
      messageDeleted(MESSAGE_ID, 'conversation-id')
    );

    assert.strictEqual(updated.audioPlayer.active?.content, undefined);
  });

  it('resets active.content when message is DOE', () => {
    const state = getInitializedState();

    const updated = rootReducer(
      state,
      messageChanged(MESSAGE_ID, 'conversation-id', {
        id: MESSAGE_ID,
        type: 'incoming',
        sent_at: 1,
        received_at: 1,
        timestamp: 1,
        conversationId: 'conversation-id',

        deletedForEveryone: true,
      })
    );

    assert.strictEqual(updated.audioPlayer.active?.content, undefined);
  });
});
