/*
 *  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/>.
 */
const Account = require('./model/Account')
const Conversation = require('./model/Conversation')

"use strict";
class JamiDaemon {
    constructor() {
        this.accounts = []
        this.dring = require("./dring.node")
        this.dring.init({
            "AccountsChanged": () => {
                console.log("AccountsChanged")
                const newAccounts = []
                JamiDaemon.vectToJs(this.dring.getAccountList()).forEach(accountId => {
                    for (const account in this.accounts) {
                        if (account.id === 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, /*int*/ code, detail) => {
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
                account.registrationState = state
                console.log("RegistrationStateChanged: " + accountId + " " + state + " " + code + " " + detail)
                if (state === "REGISTERED") {
                    /*if (tempAccounts[accountId]) {

                        const ctx = tempAccounts[accountId]
                        ctx.newUser.accountId = accountId
                        ctx.newUser.jamiId = jami.dring.getAccountDetails(accountId).get("Account.username")
                        //connectedUsers[accountId] = ctx.newUser
                        ctx.done(null, ctx.newUser)
                        delete tempAccounts[accountId]
                    }*/
                } else if (state === "ERROR_AUTH") {
                    //done(null, false)
                    //remove account
                }
            },
            "RegisteredNameFound": (accountId, state, address, name) => {
                console.log(`RegisteredNameFound: ${accountId} ${state} ${address} ${name}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
                if (state == 0) {
                    const contact = account.getContactFromCache(address)
                    contact.setRegisteredName(name)
                }
                let index = account.lookups.length - 1;
                while (index >= 0) {
                    const lookup = account.lookups[index]
                    if ((lookup.address && lookup.address === address) || (lookup.name && lookup.name === name)) {
                        lookup.resolve({address, name, state})
                        account.lookups.splice(index, 1);
                    }
                    index -= 1;
                }
            },
            "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": (accountId, conversationId) => {
                console.log(`conversationLoaded: ${accountId} ${conversationId}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
            },
            "MessageReceived": (accountId, conversationId, message) => {
                console.log(`messageReceived: ${accountId} ${conversationId}`)
                const account = this.getAccount(accountId)
                if (!account) {
                    console.log(`Unknown account ${accountId}`)
                    return
                }
                const conversation = account.getConversation(conversationId)
                if (!conversation) {
                    conversation.addMessage(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
                }
            }
        })

        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))
                const conversation = new Conversation(conversationId, accountId, members)
                account.addConversation(conversation)
            })
            this.accounts.push(account)
        })
    }

    addAccount(account) {
        const params = accountDetailsToNative(account)
        params.set("Account.type", "RING")
        return this.dring.addAccount(params)
    }
    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
    }
    /*getAccountDetails(accountId) {
        return this.mapToJs(this.dring.getAccountDetails(accountId))
    }*/
    setAccountDetails(accountId, details) {
        this.dring.setAccountDetails(accountId, 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) => {
            const account = this.getAccount(accountId)
            if (!account) {
                reject(new Error("Can't find account"))
            } else {
                account.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) => {
            const account = this.getAccount(accountId)
            if (!account) {
                reject(new Error("Can't find account"))
            } else {
                account.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
    }

    //getContactDetails

// private

    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)
            params.set("Account.enable", this.boolToStr(account.enable))
        if (account.autoAnswer)
            params.set("Account.autoAnswer", this.boolToStr(account.autoAnswer))
        if (account.ringtonePath)
            params.set("Account.ringtonePath", account.ringtonePath)
        if (account.ringtoneEnabled)
            params.set("Account.ringtoneEnabled", this.boolToStr(account.ringtoneEnabled))
        if (account.videoEnabled)
            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)
            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.publishedAddress)
            params.set("Account.publishedAddress", account.publishedAddress)
        if (account.upnpEnabled)
            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()
        map.forEach((value, key) => ret.set(key, value))
        return ret;
    }
}

module.exports = JamiDaemon;
