/*
 * Copyright (C) 2017-2021 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/>.
 */
'use strict';

import {
  Account,
  AccountConfig,
  AccountDetails,
  Contact,
  Conversation,
  Lookup,
  LookupResolveValue,
  Message,
  PromiseExecutor,
  RegistrationState,
  VolatileDetails,
} from 'jami-web-common';
import { createRequire } from 'module';
import path from 'path';

const require = createRequire(import.meta.url);

class JamiDaemon {
  private accounts: Account[];
  private readonly lookups: Lookup[];
  private readonly tempAccounts: Record<string, PromiseExecutor<string>>;
  private dring: Record<string, any>;

  constructor(onMessage: (account: Account, conversation: Conversation, message: Message) => void) {
    this.accounts = [];
    this.lookups = [];
    this.tempAccounts = {};
    this.dring = require(path.join(process.cwd(), 'jamid.node'));
    this.dring.init({
      AccountsChanged: () => {
        console.log('AccountsChanged');
        const newAccounts: Account[] = [];
        JamiDaemon.vectToJs(this.dring.getAccountList()).forEach((accountId) => {
          for (const account of this.accounts) {
            if (account.getId() === accountId) {
              newAccounts.push(account);
              return;
            }
          }
          newAccounts.push(
            new Account(
              accountId,
              JamiDaemon.mapToJs(this.dring.getAccountDetails(accountId)) as AccountDetails,
              JamiDaemon.mapToJs(this.dring.getVolatileAccountDetails(accountId)) as VolatileDetails
            )
          );
        });
        this.accounts = newAccounts;
      },
      AccountDetailsChanged: (accountId: string, details: AccountDetails) => {
        console.log(`AccountDetailsChanged ${accountId}`);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
        account.details = details;
      },
      VolatileDetailsChanged: (accountId: string, details: VolatileDetails) => {
        console.log(`VolatileDetailsChanged ${accountId}`);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
        account.volatileDetails = details;
      },
      IncomingAccountMessage: (accountId: string, from: Account, message: Message) => {
        console.log(`Received message: ${accountId} ${from} ${message}`);
        /*
                if (parser.validate(message["text/plain"]) === true) {
                    console.log(message["text/plain"])
                } else {

                    user = connectedUsers[accountId]
                    console.log(user.socketId)
                    io.to(user.socketId).emit('receivedMessage', message["text/plain"])
                    //io.emit('receivedMessage', message["text/plain"])
                }*/
      },
      RegistrationStateChanged: (accountId: string, state: RegistrationState, code: number, detail: string) => {
        console.log('RegistrationStateChanged: ' + accountId + ' ' + state + ' ' + code + ' ' + detail);
        const account: Account | undefined = this.getAccount(accountId);
        if (account) {
          account.registrationState = state;
        } else {
          console.log(`Unknown account ${accountId}`);
          return;
        }
        const ctx = this.tempAccounts[accountId];
        if (ctx) {
          if (state === 'REGISTERED') {
            account.details = JamiDaemon.mapToJs(this.dring.getAccountDetails(accountId)) as AccountDetails;
            ctx.resolve(accountId);
            delete this.tempAccounts[accountId];
          } else if (state === 'ERROR_AUTH') {
            this.dring.removeAccount(accountId);
            ctx.reject(state);
            delete this.tempAccounts[accountId];
          }
        }
      },
      RegisteredNameFound: (accountId: string, state: number, address: string, name: string) => {
        console.log(`RegisteredNameFound: ${accountId} ${state} ${address} ${name}`);
        let lookups;
        if (accountId) {
          const account = this.getAccount(accountId);
          if (!account) {
            console.log(`Unknown account ${accountId}`);
            return;
          }
          if (state === 0) {
            const contact = account.getContactFromCache(address);
            if (!contact.isRegisteredNameResolved()) contact.setRegisteredName(name);
          }
          lookups = account.lookups;
        } else {
          lookups = this.lookups;
        }
        let index = lookups.length - 1;
        while (index >= 0) {
          const lookup = lookups[index];
          if ((lookup.address && lookup.address === address) || (lookup.name && lookup.name === name)) {
            lookup.resolve({ address, name, state });
            lookups.splice(index, 1);
          }
          index -= 1;
        }
      },
      NameRegistrationEnded: (accountId: string, state: number, name: string) => {
        console.log(`NameRegistrationEnded: ${accountId} ${state} ${name}`);
        const account = this.getAccount(accountId);
        if (account) {
          if (state === 0) account.volatileDetails['Account.registeredName'] = name;
          if (account.registeringName) {
            account.registeringName.resolve(state);
            delete account.registeringName;
          }
        } else {
          console.log(`Unknown account ${accountId}`);
        }
      },
      // Conversations
      ConversationReady: (accountId: string, conversationId: string) => {
        console.log(`conversationReady: ${accountId} ${conversationId}`);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
        let conversation = account.getConversation(conversationId);
        if (!conversation) {
          const members = JamiDaemon.vectMapToJs(this.dring.getConversationMembers(accountId, conversationId));
          members.forEach((member) => (member.contact = account.getContactFromCache(member.uri)));
          conversation = new Conversation(conversationId, accountId, members);
          account.addConversation(conversation);
        }
      },
      ConversationRemoved: (accountId: string, conversationId: string) => {
        console.log(`conversationRemoved: ${accountId} ${conversationId}`);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
        account.removeConversation(conversationId);
      },
      ConversationLoaded: (id: number, accountId: string, conversationId: string, messages: Message[]) => {
        console.log(`conversationLoaded: ${accountId} ${conversationId}`);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
        const conversation = account.getConversation(conversationId);
        if (conversation) {
          //conversation.addLoadedMessages(messages)
          const request = conversation.requests[id];
          if (request) {
            request.resolve(messages);
          }
        }
      },
      MessageReceived: (accountId: string, conversationId: string, message: Message) => {
        console.log(`messageReceived: ${accountId} ${conversationId}`);
        console.log(message);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
        const conversation = account.getConversation(conversationId);
        if (conversation) {
          conversation.addMessage(message);
          if (onMessage) onMessage(account, conversation, message);
        }
      },
      ConversationRequestReceived: (accountId: string, conversationId: string, message: Message) => {
        console.log(`conversationRequestReceived: ${accountId} ${conversationId}`);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
      },
      ConversationMemberEvent: (accountId: string, conversationId: string, memberUri: string, event: number) => {
        console.log(`conversationMemberEvent: ${accountId} ${conversationId}`);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
      },
      OnConversationError: (accountId: string, conversationId: string, code: number, what: string) => {
        console.log(`onConversationError: ${accountId} ${conversationId}`);
        const account = this.getAccount(accountId);
        if (!account) {
          console.log(`Unknown account ${accountId}`);
          return;
        }
      },
      // Calls
      StateChange: (callId: string, state: string, code: number) => {
        console.log(`CallStateChange: ${callId} ${state} ${code}`);
      },
      IncomingCall: (accountId: string, callId: string, peerUri: string) => {
        console.log(`IncomingCall: ${accountId} ${callId} ${peerUri}`);
      },
      ConferenceCreated: (confId: string) => {
        console.log(`ConferenceCreated: ${confId}`);
      },
      ConferenceChanged: (accountId: string, confId: string, state: string) => {
        console.log(`ConferenceChanged: ${confId}`);
      },
      ConferenceRemoved: (confId: string) => {
        console.log(`ConferenceRemoved: ${confId}`);
      },
      OnConferenceInfosUpdated: (confId: string) => {
        console.log(`onConferenceInfosUpdated: ${confId}`);
      },
    });

    JamiDaemon.vectToJs(this.dring.getAccountList()).forEach((accountId) => {
      const account = new Account(
        accountId,
        JamiDaemon.mapToJs(this.dring.getAccountDetails(accountId)) as AccountDetails,
        JamiDaemon.mapToJs(this.dring.getVolatileAccountDetails(accountId)) as VolatileDetails
      );

      account.contacts = JamiDaemon.vectMapToJs(this.dring.getContacts(accountId)) as Contact[];

      JamiDaemon.vectToJs(this.dring.getConversations(accountId)).forEach((conversationId) => {
        const members = JamiDaemon.vectMapToJs(this.dring.getConversationMembers(accountId, conversationId));
        console.log('\n\nXMEMBERS: ', members);
        members.forEach((member) => {
          member.contact = account.getContactFromCache(member.uri);
          if (!member.contact.isRegisteredNameResolved()) {
            if (!member.uri) return;
            console.log(`lookupAddress ${accountId} ${member.uri}`, member);
            member.contact.setRegisteredName(
              new Promise((resolve: (value: LookupResolveValue) => void, reject) =>
                account.lookups.push({ address: member.uri, resolve, reject })
              ).then((result) => {
                if (result.state === 0) return result.name;
                else if (result.state === 1) return undefined;
                else return null;
              })
            );
            this.dring.lookupAddress(accountId, '', member.uri);
          }
        });
        const conversation = new Conversation(conversationId, accountId, members);
        conversation.infos = JamiDaemon.mapToJs(this.dring.conversationInfos(accountId, conversationId));
        account.addConversation(conversation);
      });

      this.accounts.push(account);
    });
  }

  addAccount(accountConfig: AccountConfig) {
    const params = this.accountDetailsToNative(accountConfig);
    params.set('Account.type', 'RING');
    return new Promise<string>((resolve, reject) => {
      const accountId = this.dring.addAccount(params);
      this.tempAccounts[accountId] = { resolve, reject };
    });
  }

  getDevices(accountId: string) {
    return JamiDaemon.mapToJs(this.dring.getKnownRingDevices(accountId));
  }

  getAccount(accountId: string) {
    for (let i = 0; i < this.accounts.length; i++) {
      const account = this.accounts[i];
      if (account.getId() === accountId) return account;
    }
    return undefined;
  }
  getAccountList() {
    return this.accounts;
  }
  registerName(accountId: string, password: string, name: string) {
    return new Promise((resolve, reject) => {
      if (!name) return reject(new Error('Invalid name'));
      const account = this.getAccount(accountId);
      if (!account) return reject(new Error("Can't find account"));
      if (account.registeringName) return reject(new Error('Username already being registered'));
      if (this.dring.registerName(accountId, password, name)) {
        account.registeringName = { name, resolve, reject };
      }
    });
  }

  getConversation(accountId: string, conversationId: string) {
    const account = this.getAccount(accountId);
    if (account) return account.getConversation(conversationId);
    return null;
  }
  getAccountDetails(accountId: string) {
    return JamiDaemon.mapToJs(this.dring.getAccountDetails(accountId));
  }
  setAccountDetails(accountId: string, details: AccountDetails) {
    this.dring.setAccountDetails(accountId, this.mapToNative(details));
  }
  getAudioOutputDeviceList() {
    return JamiDaemon.vectToJs(this.dring.getAudioOutputDeviceList());
  }
  getVolume(deviceName: string): number {
    return this.dring.getVolume(deviceName);
  }
  setVolume(deviceName: string, volume: number) {
    return this.dring.setVolume(deviceName, volume);
  }

  lookupName(accountId: string, name: string) {
    const p = new Promise((resolve, reject) => {
      if (accountId) {
        const account = this.getAccount(accountId);
        if (!account) {
          reject(new Error("Can't find account"));
        } else {
          account.lookups.push({ name, resolve, reject });
        }
      } else {
        this.lookups.push({ name, resolve, reject });
      }
    });
    this.dring.lookupName(accountId || '', '', name);
    return p;
  }

  lookupAddress(accountId: string, address: string) {
    console.log(`lookupAddress ${accountId} ${address}`);
    const p = new Promise((resolve, reject) => {
      if (accountId) {
        const account = this.getAccount(accountId);
        if (!account) {
          reject(new Error("Can't find account"));
        } else {
          account.lookups.push({ address, resolve, reject });
        }
      } else {
        this.lookups.push({ address, resolve, reject });
      }
    });
    this.dring.lookupAddress(accountId || '', '', address);
    return p;
  }

  stop() {
    this.dring.fini();
  }

  addContact(accountId: string, contactId: string) {
    this.dring.addContact(accountId, contactId);
    const details = JamiDaemon.mapToJs(this.dring.getContactDetails(accountId, contactId));
    if (details.conversationId) {
      const account = this.getAccount(accountId);
      if (account) {
        let conversation = account.getConversation(details.conversationId);
        if (!conversation) {
          const members = JamiDaemon.vectMapToJs(this.dring.getConversationMembers(accountId, details.conversationId));
          members.forEach((member) => (member.contact = account.getContactFromCache(member.uri)));
          conversation = new Conversation(details.conversationId, accountId, members);
          account.addConversation(conversation);
        }
      }
    }
    return details;
  }

  removeContact(accountId: string, contactId: string) {
    //bool ban false
    this.dring.removeContact(accountId, contactId, false);
  }

  blockContact(accountId: string, contactId: string) {
    //bool ban true
    this.dring.removeContact(accountId, contactId, true);
  }

  getContactDetails(accountId: string, contactId: string) {
    return JamiDaemon.mapToJs(this.dring.getContactDetails(accountId, contactId));
  }

  getDefaultModerators(accountId: string) {
    const account = this.getAccount(accountId);
    if (!account) {
      console.log(`Unknown account ${accountId}`);
      return {};
    }
    return JamiDaemon.vectToJs(this.dring.getDefaultModerators(accountId)).map((contactId) =>
      account.getContactFromCache(contactId)
    );
  }

  addDefaultModerator(accountId: string, uri: string) {
    this.dring.setDefaultModerator(accountId, uri, true);
  }

  removeDefaultModerator(accountId: string, uri: string) {
    this.dring.setDefaultModerator(accountId, uri, false);
  }

  sendMessage(accountId: string, conversationId: string, message: string) {
    this.dring.sendMessage(accountId, conversationId, message, '');
  }

  loadMessages(accountId: string, conversationId: string, fromMessage?: string) {
    const account = this.getAccount(accountId);
    if (!account) throw new Error('Unknown account');
    const conversation = account.getConversation(conversationId);
    if (!conversation) throw new Error(`Unknown conversation ${conversationId}`);

    return new Promise((resolve, reject) => {
      if (!conversation.requests) conversation.requests = {};
      const requestId = this.dring.loadConversationMessages(accountId, conversationId, fromMessage || '', 32);
      conversation.requests[requestId] = { resolve, reject };
    });
  }

  boolToStr(bool: boolean) {
    return bool ? 'true' : 'false';
  }

  accountDetailsToNative(account: AccountConfig) {
    const params = new this.dring.StringMap();
    if (account.managerUri) params.set('Account.managerUri', account.managerUri);
    if (account.managerUsername) params.set('Account.managerUsername', account.managerUsername);
    if (account.archivePassword) {
      params.set('Account.archivePassword', account.archivePassword);
    } /* else {
            console.log("archivePassword required")
            return
        }*/
    if (account.alias) params.set('Account.alias', account.alias);
    if (account.displayName) params.set('Account.displayName', account.displayName);
    if (account.enable !== undefined) params.set('Account.enable', this.boolToStr(account.enable));
    if (account.autoAnswer !== undefined) params.set('Account.autoAnswer', this.boolToStr(account.autoAnswer));
    if (account.autoAnswer !== undefined) params.set('Account.autoAnswer', this.boolToStr(account.autoAnswer));
    if (account.ringtonePath) params.set('Account.ringtonePath', account.ringtonePath);
    if (account.ringtoneEnabled !== undefined)
      params.set('Account.ringtoneEnabled', this.boolToStr(account.ringtoneEnabled));
    if (account.videoEnabled !== undefined) params.set('Account.videoEnabled', this.boolToStr(account.videoEnabled));
    if (account.useragent) {
      params.set('Account.useragent', account.useragent);
      params.set('Account.hasCustomUserAgent', 'TRUE');
    } else {
      params.set('Account.hasCustomUserAgent', 'FALSE');
    }
    if (account.audioPortMin) params.set('Account.audioPortMin', account.audioPortMin);
    if (account.audioPortMax) params.set('Account.audioPortMax', account.audioPortMax);
    if (account.videoPortMin) params.set('Account.videoPortMin', account.videoPortMin);
    if (account.videoPortMax) params.set('Account.videoPortMax', account.videoPortMax);
    if (account.localInterface) params.set('Account.localInterface', account.localInterface);
    if (account.publishedSameAsLocal !== undefined)
      params.set('Account.publishedSameAsLocal', this.boolToStr(account.publishedSameAsLocal));
    if (account.localPort) params.set('Account.localPort', account.localPort);
    if (account.publishedPort) params.set('Account.publishedPort', account.publishedPort);
    if (account.rendezVous !== undefined) params.set('Account.rendezVous', this.boolToStr(account.rendezVous));
    if (account.upnpEnabled !== undefined) params.set('Account.upnpEnabled', this.boolToStr(account.upnpEnabled));
    return params;
  }
  static vectToJs(vect: any) {
    const len = vect.size();
    const outputArr = new Array(len);
    for (let i = 0; i < len; i++) outputArr[i] = vect.get(i);
    return outputArr;
  }
  static mapToJs(m: any): Record<string, any> {
    const outputObj: Record<string, any> = {};
    JamiDaemon.vectToJs(m.keys()).forEach((k) => (outputObj[k] = m.get(k)));
    return outputObj;
  }
  static vectMapToJs(vectMap: any) {
    const len = vectMap.size();
    const outputArr = new Array(len);
    for (let i = 0; i < len; i++) outputArr[i] = JamiDaemon.mapToJs(vectMap.get(i));
    return outputArr;
  }

  mapToNative(map: any) {
    const ret = new this.dring.StringMap();
    for (const [key, value] of Object.entries(map)) ret.set(key, value);
    return ret;
  }
}

export default JamiDaemon;
