import type {
	Antenna,
	CustomEmoji,
	DriveFile,
	MeDetailed,
	MessagingMessage,
	Note,
	Notification,
	PageEvent,
	User,
	UserGroup,
} from "./entities";

type FIXME = any;

export type Channels = {
	main: {
		params: null;
		events: {
			notification: (payload: Notification) => void;
			mention: (payload: Note) => void;
			reply: (payload: Note) => void;
			renote: (payload: Note) => void;
			follow: (payload: User) => void; // 自分が他人をフォローしたとき
			followed: (payload: User) => void; // 他人が自分をフォローしたとき
			unfollow: (payload: User) => void; // 自分が他人をフォロー解除したとき
			meUpdated: (payload: MeDetailed) => void;
			pageEvent: (payload: PageEvent) => void;
			urlUploadFinished: (payload: { marker: string; file: DriveFile }) => void;
			readAllNotifications: () => void;
			unreadNotification: (payload: Notification) => void;
			unreadMention: (payload: Note["id"]) => void;
			readAllUnreadMentions: () => void;
			unreadSpecifiedNote: (payload: Note["id"]) => void;
			readAllUnreadSpecifiedNotes: () => void;
			readAllMessagingMessages: () => void;
			messagingMessage: (payload: MessagingMessage) => void;
			unreadMessagingMessage: (payload: MessagingMessage) => void;
			readAllAntennas: () => void;
			unreadAntenna: (payload: Antenna) => void;
			readAllAnnouncements: () => void;
			readAllChannels: () => void;
			unreadChannel: (payload: Note["id"]) => void;
			myTokenRegenerated: () => void;
			reversiNoInvites: () => void;
			reversiInvited: (payload: FIXME) => void;
			signin: (payload: FIXME) => void;
			registryUpdated: (payload: {
				scope?: string[];
				key: string;
				value: any | null;
			}) => void;
			driveFileCreated: (payload: DriveFile) => void;
			readAntenna: (payload: Antenna) => void;
			callSignal: (payload: {
				fromUserId: User["id"];
				to: string;
				toUserId?: string;
				sessionId: string;
				kind: "audio" | "video";
				signal: any;
			}) => void;
		};
		receives: null;
	};
	homeTimeline: {
		params: null;
		events: {
			note: (payload: Note) => void;
		};
		receives: null;
	};
	localTimeline: {
		params: null;
		events: {
			note: (payload: Note) => void;
		};
		receives: null;
	};
	hybridTimeline: {
		params: null;
		events: {
			note: (payload: Note) => void;
		};
		receives: null;
	};
	recommendedTimeline: {
		params: null;
		events: {
			note: (payload: Note) => void;
		};
		receives: null;
	};
	globalTimeline: {
		params: null;
		events: {
			note: (payload: Note) => void;
		};
		receives: null;
	};
	antenna: {
		params: {
			antennaId: Antenna["id"];
		};
		events: {
			note: (payload: Note) => void;
		};
		receives: null;
	};
	messaging: {
		params: {
			otherparty?: User["id"] | null;
			group?: UserGroup["id"] | null;
		};
		events: {
			message: (payload: MessagingMessage) => void;
			deleted: (payload: MessagingMessage["id"]) => void;
			read: (payload: MessagingMessage["id"][]) => void;
			typers: (payload: User[]) => void;
		};
		receives: {
			read: {
				id: MessagingMessage["id"];
			};
		};
	};
	reversi: {
		params: null;
		events: {
			invited: (payload: { user: User }) => void;
			matched: (payload: { game: any }) => void;
		};
		receives: null;
	};
	reversiGame: {
		params: {
			gameId: string;
		};
		events: {
			changeReadyStates: (payload: { user1: boolean; user2: boolean }) => void;
			updateSettings: (payload: { userId: User["id"]; key: string; value: any }) => void;
			started: (payload: { game: any }) => void;
			log: (payload: { time: number; player: boolean; operation: "put"; pos: number; id: string | null }) => void;
			ended: (payload: { winnerId: User["id"] | null; game: any }) => void;
			canceled: (payload: { userId: User["id"] }) => void;
		};
		receives: {
			ready: boolean;
			updateSettings: { key: string; value: any };
			cancel: null;
			putStone: { pos: number; id: string };
			claimTimeIsUp: null;
		};
	};
	shogi: {
		params: null;
		events: {
			invited: (payload: { user: User }) => void;
			matched: (payload: { game: any }) => void;
		};
		receives: null;
	};
	shogiGame: {
		params: {
			gameId: string;
		};
		events: {
			changeReadyStates: (payload: { user1: boolean; user2: boolean }) => void;
			started: (payload: { game: any }) => void;
			log: (payload: { id: string | null; at: number; userId: User["id"]; usi: string; sfen: string }) => void;
			ended: (payload: { winnerId: User["id"] | null; game: any }) => void;
			canceled: (payload: { userId: User["id"] }) => void;
		};
		receives: {
			ready: boolean;
			cancel: null;
			move: { usi: string; id: string };
		};
	};
	serverStats: {
		params: null;
		events: {
			stats: (payload: FIXME) => void;
		};
		receives: {
			requestLog: {
				id: string | number;
				length: number;
			};
		};
	};
	queueStats: {
		params: null;
		events: {
			stats: (payload: FIXME) => void;
		};
		receives: {
			requestLog: {
				id: string | number;
				length: number;
			};
		};
	};
};

export type NoteUpdatedEvent =
	| {
			id: Note["id"];
			type: "reacted";
			body: {
				reaction: string;
				userId: User["id"];
				groupId?: UserGroup["id"] | null;
			};
	  }
	| {
			id: Note["id"];
			type: "unreacted";
			body: {
				reaction: string;
				userId: User["id"];
				groupId?: UserGroup["id"] | null;
			};
	  }
	| {
			id: Note["id"];
			type: "deleted";
			body: {
				deletedAt: string;
			};
	  }
	| {
			id: Note["id"];
			type: "pollVoted";
			body: {
				choice: number;
				userId: User["id"];
			};
	  }
	| {
			id: Note["id"];
			type: "replied";
			body: {
				id: Note["id"];
			};
	  }
	| {
			id: Note["id"];
			type: "updated";
			body: {
				updatedAt: string;
			};
	  };

export type BroadcastEvents = {
	noteUpdated: (payload: NoteUpdatedEvent) => void;
	emojiAdded: (payload: {
		emoji: CustomEmoji;
	}) => void;
};
