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

import type { LocalizerType } from '../types/Util';
import { CallMode } from '../types/Calling';
import { missingCaseError } from './missingCaseError';
import type { CallStatus } from '../types/CallDisposition';
import {
  CallDirection,
  DirectCallStatus,
  type CallHistoryDetails,
  CallType,
} from '../types/CallDisposition';
import type { ConversationType } from '../state/ducks/conversations';
import { strictAssert } from './assert';

export type CallingNotificationType = Readonly<{
  // In some older calls, we don't have a call id, this hardens against that.
  callHistory: CallHistoryDetails | null;
  callCreator: ConversationType | null;
  activeConversationId: string | null;
  groupCallEnded: boolean | null;
  deviceCount: number;
  maxDevices: number;
}>;

function getDirectCallNotificationText(
  callDirection: CallDirection,
  callType: CallType,
  callStatus: DirectCallStatus,
  i18n: LocalizerType
): string {
  if (callStatus === DirectCallStatus.Pending) {
    if (callDirection === CallDirection.Incoming) {
      return callType === CallType.Video
        ? i18n('icu:incomingVideoCall')
        : i18n('icu:incomingAudioCall');
    }
    return callType === CallType.Video
      ? i18n('icu:outgoingVideoCall')
      : i18n('icu:outgoingAudioCall');
  }

  if (callStatus === DirectCallStatus.Accepted) {
    if (callDirection === CallDirection.Incoming) {
      return callType === CallType.Video
        ? i18n('icu:acceptedIncomingVideoCall')
        : i18n('icu:acceptedIncomingAudioCall');
    }
    return callType === CallType.Video
      ? i18n('icu:acceptedOutgoingVideoCall')
      : i18n('icu:acceptedOutgoingAudioCall');
  }

  if (callStatus === DirectCallStatus.Declined) {
    if (callDirection === CallDirection.Incoming) {
      return callType === CallType.Video
        ? i18n('icu:declinedIncomingVideoCall')
        : i18n('icu:declinedIncomingAudioCall');
    }
    return callType === CallType.Video
      ? i18n('icu:missedOrDeclinedOutgoingVideoCall')
      : i18n('icu:missedOrDeclinedOutgoingAudioCall');
  }

  if (callStatus === DirectCallStatus.Missed) {
    if (callDirection === CallDirection.Incoming) {
      return callType === CallType.Video
        ? i18n('icu:missedIncomingVideoCall')
        : i18n('icu:missedIncomingAudioCall');
    }
    return callType === CallType.Video
      ? i18n('icu:missedOrDeclinedOutgoingVideoCall')
      : i18n('icu:missedOrDeclinedOutgoingAudioCall');
  }

  if (callStatus === DirectCallStatus.Deleted) {
    throw new Error(
      'getDirectCallNotificationText: Cannot render deleted call'
    );
  }

  throw missingCaseError(callStatus);
}

function getGroupCallNotificationText(
  groupCallEnded: boolean,
  creator: ConversationType | null,
  i18n: LocalizerType
): string {
  if (groupCallEnded) {
    return i18n('icu:calling__call-notification__ended');
  }
  if (creator == null) {
    return i18n('icu:calling__call-notification__started-by-someone');
  }
  if (creator.isMe) {
    return i18n('icu:calling__call-notification__started-by-you');
  }
  return i18n('icu:calling__call-notification__started', {
    name: creator.systemGivenName ?? creator.title,
  });
}

export function getCallingNotificationText(
  callingNotification: CallingNotificationType,
  i18n: LocalizerType
): string | null {
  const { callHistory, callCreator, groupCallEnded } = callingNotification;
  if (callHistory == null) {
    return null;
  }

  if (callHistory.mode === CallMode.Direct) {
    return getDirectCallNotificationText(
      callHistory.direction,
      callHistory.type,
      callHistory.status as DirectCallStatus,
      i18n
    );
  }
  if (callHistory.mode === CallMode.Group) {
    strictAssert(
      groupCallEnded != null,
      'getCallingNotificationText: groupCallEnded shouldnt be null for a group call'
    );
    return getGroupCallNotificationText(groupCallEnded, callCreator, i18n);
  }
  throw missingCaseError(callHistory.mode);
}

type CallingIconType =
  | 'audio-incoming'
  | 'audio-missed'
  | 'audio-outgoing'
  | 'phone'
  | 'video'
  | 'video-incoming'
  | 'video-missed'
  | 'video-outgoing';

export function getCallingIcon(
  callType: CallType,
  callDirection: CallDirection,
  callStatus: CallStatus
): CallingIconType {
  if (callType === CallType.Audio) {
    if (callStatus === DirectCallStatus.Accepted) {
      return callDirection === CallDirection.Incoming
        ? 'audio-incoming'
        : 'audio-outgoing';
    }
    if (
      callStatus === DirectCallStatus.Missed ||
      callStatus === DirectCallStatus.Declined
    ) {
      return 'audio-missed';
    }
    return 'phone';
  }
  if (callType === CallType.Video) {
    if (callStatus === DirectCallStatus.Accepted) {
      return callDirection === CallDirection.Incoming
        ? 'video-incoming'
        : 'video-outgoing';
    }
    if (
      callStatus === DirectCallStatus.Missed ||
      callStatus === DirectCallStatus.Declined
    ) {
      return 'video-missed';
    }
    return 'video';
  }
  if (callType === CallType.Group) {
    return 'video';
  }
  throw missingCaseError(callType);
}
