/*
 * 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['text/plain']}`);
        /*
                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;
