var users = [];
var posts = {};

const adjectives = [
    "dynamic", "strategic", "innovative", "passionate", "results-oriented",
    "proactive", "visionary", "collaborative", "driven", "empathetic",
    "adaptable", "resilient", "resourceful", "detail-oriented", "inspirational",
    "analytical", "motivated", "solution-focused", "committed", "agile"
];

const localMode = false;
const blockContainer = document.getElementById("block-container");
const postCountElem = document.getElementById("post-count");
const postTotalElem = document.getElementById("post-total");
const loader = document.getElementById("loader");

// define a variable for how many posts we want to increase the page by
const postIncrease = 9;
// and define a value to determine which page we're on
let currentPage = 1;

// how many times can we increase the content until we reach the max limit?
function getPageCount() {
    return Math.ceil(Object.keys(posts).length / postIncrease);
}

class Post {
    // JSON post data
    constructor(data) {
        this.id = data.id;
        this.username = data.associatedUser;
        this.content = data.body;
        this.replyTo = data.replyTo;
        this.parentPost = null;

        this.replies = [];
    }

    getIsReply() {
        return this.replyTo != "";
    }

    addReply(reply) {
        this.replies.push(reply);
        reply.parentPost = this;
    }

    getPostLevel() {
        let p = this.parentPost;
        let depth = 0;
        while (p != null) {
            p = p.parentPost;
            depth++;
        }
        return depth;
    }

    getHeaderTag() {
        return this.getPostLevel() == 0 ? "h1" : "h2";
    }

    getHeaderElement() {
        const elem = document.createElement("div");
        elem.className = "post-header";
        elem.addEventListener("click", () => updateUserProfile(this.username));

        // TODO: fetch current user pfp from thispersondoesnotexist and place in local storage
        // for now if this person is us, post octopus
        const currentUser = getCurrentUser();
        const isCurrentUser = this.username == currentUser.user;
        const pfpPath = isCurrentUser ? "oct.jpg" : `user/${this.username}.png`;

        const pfpElem = document.createElement("img");
        pfpElem.setAttribute("src", pfpPath);
        pfpElem.setAttribute("class", "pfp");
        elem.appendChild(pfpElem);

        const usernameElem = document.createElement(this.getHeaderTag());
        usernameElem.setAttribute("class", "username");
        usernameElem.innerHTML = `<a href="#">${this.username}</a>`;
        elem.appendChild(usernameElem);

        return elem;
    }

    getContentElement() {
        const elem = document.createElement("p");
        elem.innerHTML = this.content;
        return elem;
    }

    getReplyButton() {
        const elem = document.createElement("a");
        const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];
        const particle = "aeiou".includes(adjective[0]) ? "an" : "a";
        elem.innerHTML = `Write ${particle} ${adjective} reply for me!`;
        elem.className = "reply-button";
        elem.addEventListener("click", () => writeReply(this));
        return elem;
    }

    getElement() {
        const elem = document.createElement("div");
        elem.id = this.id;

        // display root posts as blocks, and comments as attached to their posts
        let classes = ["post"];
        if (this.getPostLevel() == 0) {
            classes.push("block");
        }
        elem.className = classes.join(" ");
        elem.appendChild(this.getHeaderElement());
        elem.appendChild(this.getContentElement());
        elem.appendChild(this.getReplyButton());

        for (let i = 0; i < this.replies.length; i++) {
            const reply = this.replies[i];
            elem.appendChild(reply.getElement());
        }

        return elem;
    }
}


function getRootPosts() {
    let result = [];
    for (var id in posts) {
        const post = posts[id];
        if (post.getIsReply())
            continue;

        result.push(post);
    }
    return result;
}


function addPosts(pageIdx) {
    currentPage = pageIdx;

    const startRange = (pageIdx - 1) * postIncrease;
    const endRange = currentPage == getPageCount()
        ? posts.length
        : pageIdx * postIncrease;

    postCountElem.innerHTML = endRange;

    const rootPosts = getRootPosts();

    for (let i = startRange + 1; i <= endRange; i++) {
        const post = rootPosts[i];
        const elem = post.getElement();
        blockContainer.appendChild(elem);
    }
}


function handleInfiniteScroll() {
    throttle(() => {
        const endOfPage = window.innerHeight + window.pageYOffset >= document.body.offsetHeight;

        if (endOfPage) {
            addPosts(currentPage + 1);
        }

        if (currentPage === getPageCount()) {
            removeInfiniteScroll();
        }
    }, 1000);
}


// limit how often we try to load new posts to maintain browser performance
var throttleTimer;
function throttle(callback, time) {
    if (throttleTimer) return;

    throttleTimer = true;

    setTimeout(() => {
        callback();
        throttleTimer = false;
    }, time);
}


function removeInfiniteScroll() {
    loader.remove();
    window.removeEventListener("scroll", handleInfiniteScroll);
}

function getTopPost() {
    // find the first post
    const children = blockContainer.childNodes;
    let firstPost = null;
    for (let i = 0; i < children.length; i++) {
        const child = children[i];
        const classes = child.className.split(" ");
        if (classes.some(c => c == "post")) {
            firstPost = child;
            break;
        }
    }

    return firstPost;
}

function makePostFromJson(json) {
    return new Post({
        id: json.id,
        associatedUser: json.associatedUser,
        body: json.body
    });
}

function getCurrentUser() {
    return {
        "user": "theChief",
        "interests": [
            "gen-ai",
            "blockchain",
            "nfts"
        ],
        "posting_style": "just the most truly inane takes"
    };
}

function writePost(postCallback) {
    const request = {
        method: "POST",
        mode: "cors",
        body: JSON.stringify(getCurrentUser()),
        headers: {
            "Content-type": "application/json; charset=UTF-8"
        }
    };

    if (localMode) {
        const post = new Post({
            id: "1234",
            associatedUser: getCurrentUser().user,
            body: "local mode post (local mode post)"
        });
        postCallback(post);
        //blockContainer.insertBefore(post.getElement(), getTopPost());
    } else {
        fetch("https://api.wayfarer.games/singularity/generate-posts.php", request)
            .then(response => response.json())
            .then(makePostFromJson)
            //.then(post => blockContainer.insertBefore(post.getElement(), getTopPost()));
            .then(postCallback);
    }
}

function writeNewPost() {
    writePost(post => blockContainer.insertBefore(post.getElement(), getTopPost()));
}

function writeReply(post) {
    // find the correct element
    const elem = document.getElementById(post.id);

    writePost(reply => {
        post.addReply(reply);
        elem.append(reply.getElement());
    });
}


function addWritePostBlock() {
    const blockElem = document.createElement("div");
    blockElem.addEventListener("click", writeNewPost);
    blockElem.className = "block write-post";

    const spanElem = document.createElement("h2");
    spanElem.className = "";
    spanElem.innerHTML = "Write something interesting for me!";
    blockElem.append(spanElem);

    blockContainer.append(blockElem);
}

function init() {
    if (posts == undefined)
    {
        console.log("resource loading failed");
        return;
    }
    
    // need to load all the resources first
    const postCount = Object.keys(posts).length;
    if (users.length == 0 || postCount == 0)
        return;

    console.log(`loaded ${users.length} users and ${postCount} posts`);

    // TODO: add user bio above write post button
    addWritePostBlock();

    addPosts(currentPage);
    window.addEventListener("scroll", handleInfiniteScroll);
}

function loadDataFromEndpoint(endpoint, callback) {
    fetch(endpoint)
        .then(response => response.json())
        .then(json => {
            callback(json);
            init();
        });
}

const usersUrl = localMode ? "users.json" : "https://api.wayfarer.games/singularity/users.json";
const postsUrl = localMode ? "posts.json" : "https://api.wayfarer.games/singularity/posts.json";
loadDataFromEndpoint(usersUrl, json => { users = json.users; });
loadDataFromEndpoint(postsUrl, json => {
    // first pass to instantiate all the posts
    for (let i = 0; i < json.content.length; i++) {
        const post = new Post(json.content[i]);
        posts[post.id] = post;
    }

    // second pass to link each reply to the appropriate parent
    for (const id in posts) {
        const post = posts[id];
        if (!post.getIsReply())
            continue;

        const parent = posts[post.replyTo];
        parent.addReply(post);
    }

    postTotalElem.innerHTML = Object.keys(posts).length;
});
