import { tokenFromTerms } from './ldat'
import * as path from 'path'
import * as rsa from '../crypto/rsa'
const constants = require(path.join(__dirname,'../../config/constants.json'))

function addInRemoteText(full:{[k:string]:any}, contactId, isTribe:boolean){
	const m = full && full.message
	if (!(m && m.content)) return full
	if (!(typeof m.content==='object')) return full
	if(isTribe) {
		// if just one, send it (for tribe remote_text_map... is there a better way?)
		if(m.content['chat']) {
			return fillmsg(full, {content: m.content['chat']})
		}
	}
	return fillmsg(full, {content: m.content[contactId+'']})
}

function removeRecipientFromChatMembers(full:{[k:string]:any}, destkey){
	const c = full && full.chat
	if (!(c && c.members)) return full
	if (!(typeof c.members==='object')) return full

    const members = {...c.members}
	if(members[destkey]) delete members[destkey]
	return fillchatmsg(full, {members})
}

function removeAllNonAdminMembersIfTribe(full:{[k:string]:any}, destkey){
	return full
	// const c = full && full.chat
	// if (!(c && c.members)) return full
	// if (!(typeof c.members==='object')) return full

    // const members = {...c.members}
	// if(members[destkey]) delete members[destkey]
	// return fillchatmsg(full, {members})
}

// THIS IS ONLY FOR TRIBE OWNER
// by this time the content and mediaKey are already in message as string
async function encryptTribeBroadcast(full:{[k:string]:any}, contact, isTribeOwner:boolean){
	if(!isTribeOwner) return full

	const chat = full && full.chat
	const message = full && full.message
	if (!message || !(chat && chat.type && chat.uuid)) return full
	const obj: {[k:string]:any} = {}
	if(isTribeOwner) { // has been previously decrypted
		if(message.content) {
			const encContent = await rsa.encrypt(contact.contactKey, message.content)
			obj.content = encContent
		}
		if(message.mediaKey) {
			const encMediaKey = await rsa.encrypt(contact.contactKey, message.mediaKey)
			obj.mediaKey = encMediaKey
		}
	}
	return fillmsg(full, obj)
}

function addInMediaKey(full:{[k:string]:any}, contactId, isTribe:boolean){
	const m = full && full.message
	if (!(m && m.mediaKey)) return full
	if (!(m && m.mediaTerms)) return full
	if (!(typeof m.mediaKey==='object')) return full

	if(isTribe) {
		if(m.mediaKey['chat']) { // "chat" is the key for tribes
			const tribeMediaKey = m.mediaTerms.skipSigning?'':m.mediaKey['chat']
			return fillmsg(full, {mediaKey:tribeMediaKey})
		}
	}
	const mediaKey = m.mediaTerms.skipSigning ? '' : m.mediaKey[contactId+'']
	return fillmsg(full, {mediaKey})
}

// add the token if its free, but if a price just the base64(host).muid
async function finishTermsAndReceipt(full:{[k:string]:any}, destkey) {
	const m = full && full.message
	if (!(m && m.mediaTerms)) return full

	const t = m.mediaTerms
	const meta = t.meta || {}
	t.ttl = t.ttl || 31536000
	meta.ttl = t.ttl
	const mediaToken = await tokenFromTerms({
		host: t.host || '',
		muid: t.muid,
		ttl: t.skipSigning ? 0 : t.ttl,
		pubkey: t.skipSigning ? '' : destkey,
		meta
	})
	const fullmsg = fillmsg(full, {mediaToken})
	delete fullmsg.message.mediaTerms
	return fullmsg
}

// this is only for tribes
// DECRYPT EITHER STRING OR FIRST VAL IN OBJ
async function decryptMessage(full:{[k:string]:any}, chat) {
	if(!chat.groupPrivateKey) return full
	const m = full && full.message
	if (!m) return full

	const obj: {[k:string]:any} = {}
	if(m.content) {
		let content = m.content
		if(typeof m.content==='object') {
			if(m.content['chat']) {
				content = m.content['chat']
			}
		}
		const decContent = rsa.decrypt(chat.groupPrivateKey, content)
		obj.content = decContent
	}
	if (m.mediaKey) {
		let mediaKey = m.mediaKey
		if(typeof m.mediaKey==='object') {
			if(m.mediaKey['chat']) {
				mediaKey = m.mediaKey['chat']
			}
		}
		const decMediaKey = rsa.decrypt(chat.groupPrivateKey, mediaKey)
		obj.mediaKey = decMediaKey
	}

	// console.log("OBJ FILLED",fillmsg(full, obj))
	return fillmsg(full, obj)
}

async function personalizeMessage(m,contact,isTribeOwner:boolean){
	const contactId = contact.id
	const destkey = contact.publicKey
	
	const cloned = JSON.parse(JSON.stringify(m))

	const chat = cloned && cloned.chat
	const isTribe = chat.type&&chat.type===constants.chat_types.tribe

	const msgWithRemoteTxt = addInRemoteText(cloned, contactId, isTribe)
	const cleanMsg = removeRecipientFromChatMembers(msgWithRemoteTxt, destkey)
	const cleanerMsg = removeAllNonAdminMembersIfTribe(cleanMsg, destkey)
	const msgWithMediaKey = addInMediaKey(cleanerMsg, contactId, isTribe)
	const msgWithMediaToken = await finishTermsAndReceipt(msgWithMediaKey, destkey)
	const encMsg = await encryptTribeBroadcast(msgWithMediaToken, contact, isTribeOwner)
    return encMsg
}

function fillmsg(full, props){
	return {
		...full, message: {
			...full.message,
			...props,
		}
	}
}

function fillchatmsg(full, props){
	return {
		...full, chat: {
			...full.chat,
			...props,
		}
	}
}

export {
    personalizeMessage, decryptMessage, encryptTribeBroadcast,
}