import type {
    CspE2eContactControlType,
    CspE2eConversationType,
    CspE2eGroupControlType,
    CspE2eGroupConversationType,
    CspE2eGroupStatusUpdateType,
    CspE2eStatusUpdateType,
} from '~/common/enum';
import type {CspE2eType} from '~/common/network/protocol';

import * as DeliveryReceipt from './delivery-receipt';
import * as File from './file';
import * as GroupCreatorContainer from './group-creator-container';
import * as GroupMemberContainer from './group-member-container';
import * as GroupName from './group-name';
import * as GroupSetup from './group-setup';
import * as Location from './location';
import * as PollSetup from './poll-setup';
import * as PollVote from './poll-vote';
import * as SetProfilePicture from './set-profile-picture';
import * as Text from './text';
import * as TypingIndicator from './typing-indicator';

export {
    DeliveryReceipt,
    File,
    GroupCreatorContainer,
    GroupMemberContainer,
    Location,
    PollSetup,
    PollVote,
    GroupName,
    GroupSetup,
    SetProfilePicture,
    Text,
    TypingIndicator,
};

/**
 * A validated message with its payload type.
 */
interface ValidatedCspE2eMessageType<
    T extends CspE2eType,
    P,
    C extends GroupMemberContainer.Type | GroupCreatorContainer.Type | undefined = undefined,
> {
    type: T;
    message: P;
    container: C;
}

/**
 * All possible validated message types.
 */
export type ValidatedCspE2eTypesStructbuf =
    // Contact conversation messages
    | ValidatedCspE2eMessageType<CspE2eConversationType.TEXT, Text.Type>
    | ValidatedCspE2eMessageType<CspE2eConversationType.FILE, File.Type>
    | ValidatedCspE2eMessageType<CspE2eConversationType.LOCATION, Location.Type>
    | ValidatedCspE2eMessageType<CspE2eConversationType.POLL_SETUP, PollSetup.Type>
    | ValidatedCspE2eMessageType<CspE2eConversationType.POLL_VOTE, PollVote.Type>

    // Contact Control Messages
    | ValidatedCspE2eMessageType<
          CspE2eContactControlType.CONTACT_REQUEST_PROFILE_PICTURE,
          undefined
      >

    // Group conversation messages
    | ValidatedCspE2eMessageType<
          CspE2eGroupConversationType.GROUP_TEXT,
          Text.Type,
          GroupMemberContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupConversationType.GROUP_FILE,
          File.Type,
          GroupMemberContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupConversationType.GROUP_LOCATION,
          Location.Type,
          GroupMemberContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupConversationType.GROUP_POLL_SETUP,
          PollSetup.Type,
          GroupMemberContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupConversationType.GROUP_POLL_VOTE,
          PollVote.Type,
          GroupMemberContainer.Type
      >

    // Group control messages
    | ValidatedCspE2eMessageType<
          CspE2eGroupControlType.GROUP_SETUP,
          GroupSetup.Type,
          GroupCreatorContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupControlType.GROUP_NAME,
          GroupName.Type,
          GroupCreatorContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupControlType.GROUP_SET_PROFILE_PICTURE,
          SetProfilePicture.Type,
          GroupCreatorContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupControlType.GROUP_DELETE_PROFILE_PICTURE,
          undefined,
          GroupCreatorContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupControlType.GROUP_LEAVE,
          undefined,
          GroupMemberContainer.Type
      >
    | ValidatedCspE2eMessageType<
          CspE2eGroupControlType.GROUP_SYNC_REQUEST,
          undefined,
          GroupCreatorContainer.Type
      >

    // Status messages
    | ValidatedCspE2eMessageType<CspE2eStatusUpdateType.DELIVERY_RECEIPT, DeliveryReceipt.Type>
    | ValidatedCspE2eMessageType<CspE2eStatusUpdateType.TYPING_INDICATOR, TypingIndicator.Type>
    | ValidatedCspE2eMessageType<
          CspE2eGroupStatusUpdateType.GROUP_DELIVERY_RECEIPT,
          DeliveryReceipt.Type,
          GroupMemberContainer.Type
      >;
