/*
 Copyright (C) 2020 - 2025 3NSoft Inc.

 This program is free software: you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation, either version 3 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 this program. If not, see <http://www.gnu.org/licenses/>.
*/

import type { ItemForTemplate } from "../src-main/utils/template-iterator-keys.ts";
import { StoredInvitationParams, ChatIdObj, ChatSystemMessageData, RelatedMessage } from "./asmail-msgs.types.ts";

export interface ChatViewBase extends ChatIdObj {
  name: string;
  createdAt: number;
  lastUpdatedAt: number;
}

export interface SingleChatView extends ChatViewBase {
  isGroupChat: false;
  peerAddr: string;
  status: SingleChatStatus;
}

export type SingleChatStatus = 'initiated' | 'on' | 'peer-left' | 'invited';

export interface GroupChatView extends ChatViewBase {
  isGroupChat: true;
  members: string[];
  admins: string[];
  status: GroupChatStatus;
}

export type GroupChatStatus = 'initiated' | 'partially-on' | 'on' | 'all-left' | 'invited';

export type ChatView = SingleChatView | GroupChatView;

export interface ChatMessageAttachmentsInfo {
  id?: string;
  name: string;
  size: number;
}

export interface ChatMessageViewBase {

  chatId: ChatIdObj;

  /**
   * chatMessageId is generated by sender. It should be unique within a chat.
   * Expected form is an epoch in 100's of seconds, dash, short random part,
   * e.g. `${Math.floor(Date.now()/(100*1000))}-${randomString}` yielding
   * something like 17469720-eAkJmPpW.
   * A ballpark epoch extractable from chatMessageId allows for more efficient
   * lookup in implementation of message storage/dataset.
   */
  chatMessageId: string;

  timestamp: number;

  isIncomingMsg: boolean;

  /**
   * incomingMsgId presence indicates that this is an incoming message, and its
   * value identifies message in the inbox, as it is generated by receiving
   * ASMail server.
   * Database needs to know if message is incoming, but actual id value is
   * needed only when there are bytes in inbox, like with attachments.
   * Otherwise, message can be removed and id's value isn't needed.
   */
  incomingMsgId?: web3n.asmail.IncomingMessage['msgId'];

  sender: string;

} 

export interface RegularMsgView extends ChatMessageViewBase {

  /**
   * chatMessageType indicates type of message
   */
  chatMessageType: 'regular';

  /**
   * relatedMessage reference other chat message.
   */
  relatedMessage?: {
    replyTo?: RegularMsgView;
    forwardingOf?: RegularMsgView;
    msgNotFound?: true;
  };

  body: string;
  status: MessageStatus;
  attachments?: ChatMessageAttachmentsInfo[];

}

export interface ChatSysMsgView extends ChatMessageViewBase {

  /**
   * chatMessageType indicates type of message
   */
  chatMessageType: 'system';

  systemData: ChatSystemMessageData;
  status?: undefined;

}

export interface ChatInvitationMsgView extends ChatMessageViewBase {

  /**
   * chatMessageType indicates type of message
   */
  chatMessageType: 'invitation';

  inviteData: StoredInvitationParams;
  status?: undefined;

}

export type ChatMessageView = (
  RegularMsgView
  | ChatSysMsgView
  | ChatInvitationMsgView
) & ItemForTemplate;

export type IncomingMessageStatus = 'read' | 'unread';

export type OutgoingMessageStatus =
  'sending'
  | 'sending:some-done'
  | 'sent'
  | 'sent:all-failed'
  | 'sent:some-failed'
  | 'sent:canceled'
  | 'received'
  | 'received:some'
  | 'read'
  | 'read:some';

export type MessageStatus = IncomingMessageStatus | OutgoingMessageStatus;

export type ChatMessageActionType =
  'reply'
  | 'copy'
  | 'forward'
  | 'download'
  | 'resend'
  | 'delete_message'
  | 'cancel_sending';

export interface ChatMessageAction {
  id: ChatMessageActionType;
  icon: {
    name: string;
    horizontalFlip?: boolean;
    rotateIcon?: 1 | 2 | 3,
  };
  title: string;
  conditions: string[];
  blockStart?: boolean;
  accent?: string;
  disabled?: boolean;
}

export type ChatListItemView = ChatView & {
  unread: number;
  lastMsg?: ChatMessageView;
} & ItemForTemplate;

export interface LocalMetadataInDelivery {
  chatId: ChatIdObj;
  chatMessageId?: ChatMessageView['chatMessageId'];
  chatMessageType: ChatMessageView['chatMessageType'];
  chatSystemData?: ChatSystemMessageData;
}
