import { z } from 'zod';

export default class Post  {
    prefix = "POST"
    indices = null

    constructor(indices) {
        this.indices = indices
    }
    
    schema = z.object({
        id: z.number(),
        text: z.string(),
        time: z.string(),
        sentBy: z.string(),
        edited: z.boolean()
    })

    makeID(forum, number) {
        // return `POST-${forum}-${number}`
        return `POST-${number}`
    }

    save(post, id) {
        let result = this.schema.safeParse(post)
        if(result.success) {
            try {
                super.add(id, post)
            } catch(e) {
                console.error(e)
                throw e
            }
        } else {
            console.error("Failed parsing member: ", result.error)
            throw new global.ServerError(400, "Invalid Member Data!: ");
        }
    }

    get(forum, by, authorId = null) {
        let result = []
        if (by === "member" && authorId) {
            result = this.getByMember(authorId)
        } else { // network
            let { id: networkId } = global.db.networks.getByAbbreviation(forum)
            result = this.getByNetwork(networkId)
        }
        return result
    }

    getByID(id) {
        if(typeof id === 'string') {
            id = id.split("-")[1]
        }
        return {
            id,
            authorId: this.getAuthor(id),
            ...global.db.nodes[this.indices[0] + (id - 1)]
        }
    }

    getAuthor(postId) {
        return db.POST_BY_MEMBER.getAuthorId(`${this.prefix}-${postId}`);
    }

    getByNetwork(id) {
        let connections = db.POST_FROM_NETWORK.getByNetwork(id)
        let posts = []
        connections.forEach((conn) => {
            posts.push(this.getByID(conn.from))
        })
        return posts
    }

    getByMember(stringID) {
        let connections = db.POST_BY_MEMBER.getByMember(stringID)
        let posts = []
        connections.forEach((conn) => {
            posts.push(this.getByID(conn.from))
        })
        return posts
    }

    async edit(id, text, userEmail) {
        try {
            let userId = global.db.members.getByEmail(userEmail).id
            let postToEdit = this.getByID(id)

            if (postToEdit.authorId !== userId) {
                throw new global.ServerError(401, "Not authorized to delete post!")
            }

            postToEdit.text = text
            postToEdit.time = global.currentTime()
            postToEdit.edited = true;
            
            let { authorId, ...rest } = postToEdit
            global.db.updateNode(this.prefix, id, rest)

            return postToEdit
        } catch(e) {
            console.error(e)
            throw new global.ServerError(400, "Failed to delete post!")
        }
    }

    async delete(id, forum, userEmail) {
        try {
            let userId = global.db.members.getByEmail(userEmail).id 
            let network = global.db.networks.getByAbbreviation(forum)

            if (this.getAuthor(id) !== userId) {
                throw new global.ServerError(401, "Not authorized to delete post!")
            }

            global.db.deleteNode(this.prefix, id)
            
            if(network) {
                global.db.edge.delete({
                    type: "FROM",
                    from: `${this.prefix}-${id}`,
                    to: `NETWORK-${network.id}`
                })
            }
            global.db.edge.delete({
                type: "BY",
                from: `${this.prefix}-${id}`,
                to: `MEMBER-${userId}`
            })
        } catch(e) {
            console.error(e)
            throw new global.ServerError(400, "Failed to delete post!")
        }
    }

    async add(text, forum, userEmail) {
        let newPost = {}
        let sender = global.db.members.getByEmail(userEmail)
        let network = global.db.networks.getByAbbreviation(forum)

        newPost.text = text
        newPost.time = global.currentTime()
    
        try {
            newPost.sentBy = `${sender.firstName} ${sender.lastName}`

            global.db.addNode(this.prefix, newPost)
            if(network) {
                global.db.edge.add({
                    type: "FROM",
                    from: `${this.prefix}-${global.db.getCurrentIndex(this)}`,
                    to: `NETWORK-${network.id}`
                })
            }
            global.db.edge.add({
                type: "BY",
                from: `${this.prefix}-${global.db.getCurrentIndex(this)}`,
                to: `MEMBER-${sender.id}`
                })
            return `${this.prefix}-${global.db.getCurrentIndex(this)}`
        } catch(e) {
            console.error(e)
            throw new global.ServerError(400, "Failed to add member!");
        }
    }
}