/*
 * Copyright (C) 2022 Savoir-faire Linux Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program.  If not, see
 * <https://www.gnu.org/licenses/>.
 */
import { Contact } from './Contact.js';
import { PromiseExecutor } from './util.js';

export interface ConversationMember {
  contact: Contact;
  role?: 'admin' | 'member' | 'invited' | 'banned' | 'left';
}

type ConversationInfos = Record<string, unknown>;

export interface Message {
  id: string;
  author: string;
  timestamp: string;
  type:
    | 'application/call-history+json'
    | 'application/data-transfer+json'
    | 'application/update-profile'
    | 'initial'
    | 'member'
    | 'merge'
    | 'text/plain'
    | 'vote';
  linearizedParent: string;
  parents: string;
  body?: string;
  duration?: string;
  to?: string;
  invited?: string;
}

type ConversationRequest = PromiseExecutor<Message[]>;

type ConversationListeners = Record<
  string,
  {
    socket: any; // TODO: Improve typing
    session: any;
  }
>;

export class Conversation {
  private readonly id: string | undefined;
  private readonly accountId: string;
  private readonly members: ConversationMember[];
  private messages: Message[];
  private _infos: ConversationInfos;
  private _requests: Record<string, ConversationRequest>;
  private _listeners: ConversationListeners;

  constructor(id: string | undefined, accountId: string, members?: ConversationMember[]) {
    this.id = id;
    this.accountId = accountId;
    this.members = members || [];

    this.messages = [];
    this._infos = {};
    this._requests = {};
    this._listeners = {};
  }

  static from(accountId: string, object: any) {
    const conversation = new Conversation(
      object.id,
      accountId,
      object.members.map((member: any) => {
        member.contact = Contact.from(member.contact);
        return member;
      })
    );
    conversation.messages = object.messages;
    conversation.infos = object.infos;
    return conversation;
  }
  static fromSingleContact(accountId: string, contact: Contact) {
    return new Conversation(undefined, accountId, [{ contact }]);
  }

  getId() {
    return this.id;
  }

  getAccountId() {
    return this.accountId;
  }

  getDisplayName() {
    if (this.members.length !== 0) {
      return this.members[0].contact.getDisplayName();
    }
    return this.getDisplayUri();
  }

  getDisplayNameNoFallback() {
    if (this.members.length !== 0) {
      return this.members[0].contact.getDisplayNameNoFallback();
    }
  }

  async getObject(params?: {
    memberFilter: (value: ConversationMember, index: number, array: ConversationMember[]) => boolean;
  }) {
    const members = params?.memberFilter ? this.members.filter(params.memberFilter) : this.members;
    return {
      id: this.id,
      messages: this.messages,
      members: await Promise.all(
        members.map(async (member) => {
          //Object.assign({}, member);
          return {
            role: member.role,
            contact: await member.contact.getObject(),
          };
        })
      ),
      infos: this._infos,
    };
  }

  getSummary() {
    return this.getObject();
  }

  getDisplayUri() {
    return this.getId() || this.getFirstMember().contact.getUri();
  }

  getFirstMember() {
    return this.members[0];
  }

  getMembers() {
    return this.members;
  }

  addMessage(message: Message) {
    if (this.messages.length === 0) this.messages.push(message);
    else if (message.id === this.messages[this.messages.length - 1].linearizedParent) {
      this.messages.push(message);
    } else if (message.linearizedParent === this.messages[0].id) {
      this.messages.unshift(message);
    } else {
      console.log("Can't insert message " + message.id);
    }
  }

  addLoadedMessages(messages: Message[]) {
    messages.forEach((message) => this.addMessage(message));
  }

  getMessages() {
    return this.messages;
  }

  get infos() {
    return this._infos;
  }

  set infos(infos: ConversationInfos) {
    this._infos = infos;
  }

  get requests(): Record<string, ConversationRequest> {
    return this._requests;
  }

  set requests(value: Record<string, ConversationRequest>) {
    this._requests = value;
  }

  get listeners(): ConversationListeners {
    return this._listeners;
  }

  set listeners(listeners: ConversationListeners) {
    this._listeners = listeners;
  }
}
