/*
 *  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("./dring.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))
            )
            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)
            })
            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 }
        })
    }
    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 this.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
    }

    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
