/*
 *  Copyright (c) 2017-2021 Savoir-faire Linux Inc.
 *
 *  Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
 *  Author: Asad Salman <me@asad.co>
 *
 *  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 <https://www.gnu.org/licenses/>.
 */
"use strict"

import Account from './model/Account.js'
import Conversation from './model/Conversation.js'
import { createRequire } from 'module';
const require = createRequire(import.meta.url);

class JamiDaemon {
    constructor(onMessage) {
        this.accounts = []
        this.lookups = []
        this.tempAccounts = []
        this.dring = require("./jamid.node")
        this.dring.init({
            AccountsChanged: () => {
                console.log("AccountsChanged")
                const newAccounts = []
                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)),
                        JamiDaemon.mapToJs(this.dring.getVolatileAccountDetails(accountId))
                    ))
                })
                this.accounts = newAccounts
            },
            AccountDetailsChanged: (accountId, details) => {
                console.log(`AccountDetailsChanged ${accountId}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
                account.details = details
            },
            VolatileDetailsChanged: (accountId, details) => {
                console.log(`VolatileDetailsChanged ${accountId}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
                account.volatileDetails = details
            },
            IncomingAccountMessage: (accountId, from, 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, state, code, detail) => {
                console.log("RegistrationStateChanged: " + accountId + " " + state + " " + code + " " + detail)
                const account = this.getAccount(accountId)
                if (account) {
                    account.registrationState = state
                } else {
                    console.log(`Unknown account ${accountId}`)
                }
                const ctx = this.tempAccounts[accountId]
                if (ctx) {
                    if (state === "REGISTERED") {
                        account.details = JamiDaemon.mapToJs(this.dring.getAccountDetails(accountId))
                        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, state, address, name) => {
                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, state, name) => {
                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, conversationId) => {
                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, conversationId) => {
                console.log(`conversationRemoved: ${accountId} ${conversationId}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
                account.removeConversation(conversationId)
            },
            ConversationLoaded: (id, accountId, conversationId, messages) => {
                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, conversationId, 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, conversationId, request) => {
                console.log(`conversationRequestReceived: ${accountId} ${conversationId}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
            },
            ConversationMemberEvent: (accountId, conversationId, member, event) => {
                console.log(`conversationMemberEvent: ${accountId} ${conversationId}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
            },
            OnConversationError: (accountId, conversationId, code, what) => {
                console.log(`onConversationError: ${accountId} ${conversationId}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
            },
            // Calls
            StateChange: (callId, state, code) => {
                console.log(`CallStateChange: ${callId} ${state} ${code}`)
            },
            IncomingCall: (accountId, callId, peerUri) => {
                console.log(`IncomingCall: ${accountId} ${callId} ${peerUri}`)
            },
            ConferenceCreated: (confId) => {
                console.log(`ConferenceCreated: ${confId}`)
            },
            ConferenceChanged: (confId, state) => {
                console.log(`ConferenceChanged: ${confId}`)

            },
            ConferenceRemoved: (confId) => {
                console.log(`ConferenceRemoved: ${confId}`)

            },
            onConferenceInfosUpdated: (confId, info) => {
                console.log(`onConferenceInfosUpdated: ${confId}`)

            }
        })

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

            account.contacts = JamiDaemon.vectMapToJs(
              this.dring.getContacts(accountId)
            );

            JamiDaemon.vectToJs(this.dring.getConversations(accountId)).forEach(conversationId => {
                const members = JamiDaemon.vectMapToJs(this.dring.getConversationMembers(accountId, conversationId))
                members.forEach(member => {
                    member.contact = account.getContactFromCache(member.uri)
                    if (!member.contact.isRegisteredNameResolved()) {
                        if (!member.uri) return
                        console.log(`lookupAddress ${accountId} ${member.uri}`)
                        member.contact.setRegisteredName(new Promise((resolve, 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)
                account.addConversation(conversation)
            })
            account.setDevices(
            );

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

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

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

    getAccount(accountId) {
        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, password, name) {
        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, conversationId) {
        const account = this.getAccount(accountId)
        if (account)
            return account.getConversation(conversationId)
        return null
    }
    getAccountDetails(accountId) {
        return JamiDaemon.mapToJs(this.dring.getAccountDetails(accountId))
    }
    setAccountDetails(accountId, details) {
        this.dring.setAccountDetails(accountId, this.mapToNative(details))
    }
    getAudioOutputDeviceList() {
        return JamiDaemon.vectToJs(this.dring.getAudioOutputDeviceList())
    }
    getVolume(deviceName) {
        return this.dring.getVolume(deviceName)
    }
    setVolume(deviceName, volume) {
        return this.dring.setVolume(deviceName, volume)
    }

    lookupName(accountId, name) {
        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, address) {
        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, contactId) {
        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, contactId){
        //bool ban false
        this.dring.removeContact(accountId, contactId, false);
    }

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

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

    getDefaultModerators(accountId) {
        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, uri) {
        this.dring.setDefaultModerator(accountId, uri, true)
    }

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

    sendMessage(accountId, conversationId, message) {
        this.dring.sendMessage(accountId, conversationId, message, "")
    }

    loadMessages(accountId, conversationId, fromMessage) {
        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) {
        return bool ? "true" : "false"
    }

    accountDetailsToNative(account) {
        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) {
        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) {
        const outputObj = {}
        JamiDaemon.vectToJs(m.keys())
            .forEach(k => outputObj[k] = m.get(k))
        return outputObj
    }
    static vectMapToJs(vectMap) {
        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){
        const ret = new this.dring.StringMap()
        for (const [key, value] of Object.entries(map))
            ret.set(key, value)
        return ret
    }
}

export default JamiDaemon
