import {ChatEventBase, ChatEventType, ChatEventSubtype} from './eventBase';
import {DeliverStatus, MessageEvent} from './message';
import {ReadMembership, MembershipFromServer} from './membership';
import {Reaction, ReactionEvent} from './reaction';
import {HighlightedSpan} from './highlightedSpan';
import {AssetFromServer} from './asset';
import {ConversationProperties} from './conversationProperties';

export interface ImCreatedEvent extends ChatEventBase<ChatEventType.imCreated> {
  metadata: {
    event_payload: {
      users: number[];
    };
  };
}

export type NewMessageEvent = MessageEvent & {
  type: ChatEventType.message;
  subtype:
    | ChatEventSubtype.meMessage
    | ChatEventSubtype.channelCreated
    | ChatEventSubtype.messagePinAdded;
};

export interface ConversationMarkedEvent
  extends ChatEventBase<ChatEventType.channelMarked> {
  channel: string;
  user: string;
  ts: string;
  username: string;
  hu_data: ChatEventBase<ChatEventType.channelMarked>['hu_data'] & {
    message_ts: string;
    membership: ReadMembership;
  };
}

export interface ChannelCreatedEvent
  extends ChatEventBase<ChatEventType.channelCreated> {
  metadata: {event_payload: {admin: string; name: string}};
}

export interface ChannelJoinedEvent
  extends ChatEventBase<ChatEventType.channelJoined> {
  metadata: {
    event_payload: {users: string[]; memberships: MembershipFromServer[]};
  };
}

export interface ChannelLeftEvent
  extends ChatEventBase<ChatEventType.channelLeft> {
  metadata: {event_payload: {user: string; membership: MembershipFromServer}};
}

export interface AdminAddedEvent
  extends ChatEventBase<ChatEventType.channelAdminGranted> {
  metadata: {
    event_payload: {
      user: string;
      membership: MembershipFromServer;
    };
  };
}

export interface AdminRemovedEvent
  extends ChatEventBase<ChatEventType.channelAdminGranted> {
  metadata: {
    event_payload: {
      user: string;
      membership: MembershipFromServer;
    };
  };
}

export interface ChannelChangedEvent
  extends ChatEventBase<ChatEventType.channelChanged> {
  metadata: {
    event_payload: {
      oldPictureId?: string;
      newPictureId?: string;
      newName?: string;
      oldName?: string;
      newDescription?: string;
    };
  };
}

export type MessageEditedEvent = MessageEvent & {
  type: ChatEventType.messageUpdate;
  subtype: ChatEventSubtype.messageUpdate;
};

export type MessageDeletedEvent = MessageEvent & {
  type: ChatEventType.messageDeleted;
  subtype: ChatEventSubtype.messageDelete;
};
export interface AssetChangedEvent
  extends ChatEventBase<ChatEventType.attachmentChanged> {
  hu_data: {
    version: number;
    position: number;
    message_ts: string;
    sender_id: number;
    picture_url?: string;
    picture_asset_url?: string;
    highlighted_spans: HighlightedSpan[];
    read_status?: DeliverStatus;
  };
  hidden?: boolean;
  text: string;
  attachments: AssetFromServer[];
  reactions: Reaction[];
  client_msg_id: string;
}

export interface MarkedReceivedEvent
  extends ChatEventBase<ChatEventType.markedReceived> {
  metadata: {
    event_payload: {
      from_message_ts: string;
      to_message_ts: string;
      received_at: number;
    };
  };
}

export interface MarkedReadEvent
  extends ChatEventBase<ChatEventType.markedRead> {
  metadata: {
    event_payload: {
      from_message_ts: string;
      to_message_ts: string;
      read_at: number;
    };
  };
}

export interface ChannelInfoChangedEvent
  extends ChatEventBase<ChatEventType.channelInfoChanged> {
  hu_data: {
    version: number;
    position: number;
  };
  channel: string;
  user: string;
  username: string;
  external_id: string;
  ts: string;
  metadata: {
    event_payload: ConversationProperties['notification_status'] & {
      pinned_at?: number;
      marked_unread_at?: number;
      version: number;
    };
  };
}

export type PinAddedEvent = MessageEvent & {
  type: ChatEventType.messagePin;
  subtype: ChatEventSubtype.add;
};

export type PinRemovedEvent = MessageEvent & {
  type: ChatEventType.messagePin;
  subtype: ChatEventSubtype.remove;
};

export interface MessageReadByAllEvent
  extends ChatEventBase<
    ChatEventType.messageReadByAll,
    ChatEventSubtype.messageReadByAll
  > {
  metadata: {
    event_payload: {
      message_ts: string;
    };
  };
}
/**
 * Chat events
 */
export type ChatEvent =
  | NewMessageEvent
  | ImCreatedEvent
  | ConversationMarkedEvent
  | ChannelCreatedEvent
  | ChannelJoinedEvent
  | ChannelLeftEvent
  | AdminAddedEvent
  | AdminRemovedEvent
  | ChannelChangedEvent
  | MessageEditedEvent
  | MessageDeletedEvent
  | MessageReadByAllEvent
  | ReactionEvent;
