import React, {useState, useEffect, useRef} from "react";
import {Route, Routes, useLocation, useNavigate} from "react-router-dom";


import Button from "components/button/Button.jsx";
import Submission from "components/submission/Submission.jsx";
import Post from "components/post/Post.jsx";
import {getSubreactFromLocation} from "helpers/Location.jsx";

import styles from "./Posts.css";

async function makePostsRequest(location, setPosts, setError, mounted) {
    const init = {
        method: "GET",
        referrer: "same-origin",
    }
    const url = "/api/posts?" + new URLSearchParams({
        page: 0,
        amount: 25,
        subreact: getSubreactFromLocation(location),
    });
    return fetch(url, init)
        .then((response) => {
            return response.json()
                .catch(() => {
                    throw new Error("unexpected response from server")
                })
        })
        .then((json) => {
            if ("error" in json) {
                throw new Error(json.error);
            }
            if (!mounted) {
                return;
            }
            setPosts(json.posts);
        })
        .catch((error) => {
            console.log(error);
            if (!mounted) {
                return;
            }
            setError(error.message); 
        });
}

function PostsError({navigate, error}) {
    return (
        <div className={styles.container + " " + styles.containerFade}>
            <h1>Something's wrong!</h1>
            <h2>Sorry, but an unexpected issue has forced us to stop early. Here are the technical details:</h2>
            <h3>Error: {error}</h3>
            <Button onClick={() => {navigate(0);}}>
                Try again
            </Button>
        </div>
    );
}

function PostsLoading() {
    return (
        <div className={styles.container + " " + styles.containerLoading}>
            {[...Array(3)].map((_, i) =>
                <Post placeholder key={i} />
            )}
        </div>
    );
}

function PostsEmpty({navigate}) {
    return (
        <div className={styles.container + " " + styles.containerFade}>
            <h1>There's nothing here?!?</h1>
            <h2>Try changing subreacts.</h2>
            <Button onClick={() => {navigate("/");}}>
                Take me home
            </Button>
        </div>
    );
}

function PostsStates({error, posts, navigate}) {
    if (error !== null) { // Error message.
        return (
            <PostsError navigate={navigate} error={error} />
        );
    }

    if (posts == null) {
        return (
            <PostsLoading />
        )
    }


    if (posts.length == 0) {
        return (
            <PostsEmpty navigate={navigate} />
        );
    }

    return (
        posts.map(({uid, title, contents, time_updated, thumbnail, subreact}, i) => 
            <Post key={i}
                    uid={uid} 
                    title={title}
                    contents={contents}
                    timeUpdated={time_updated}
                    image={thumbnail}
                    subreact={subreact} />)
    );
}

export default function Posts() {
    const navigate = useNavigate();
    const location = useLocation();
    const locationRef = useRef(location);

    const [posts, setPosts] = useState(null);
    const [error, setError] = useState(null);
    const [submissionActive, setSubmissionActive] = useState(false);


    // We make a request if we're at the homepage or if we're changing subreacts.
    const shouldMakeRequest = () => {
        if (posts === null) {
            return true;
        }
        const [previous, current] = 
            [locationRef.current, location].map((loc) => getSubreactFromLocation(loc));
        return previous != current;
    };
    // This is a bit ugly, we're caching off our previous location so that we know
    // if we should update or not. 
    useEffect(() => {
        let mounted = true;

        if (shouldMakeRequest()) {
            setPosts(null);
            makePostsRequest(location, setPosts, setError, mounted);
        }

        locationRef.current = location;
        return () => {
            setError(null);
            mounted = false;
        }
    }, [location]);

    return (
        <div className={styles.container}>
            <div className={styles.containerPadding}>
                <div className={styles.postContainer + (submissionActive ? " " + styles.postContainerActive : "")}
                    onClick={(submissionActive ? () => {setSubmissionActive(false);} : null)}>
                        <div className={(submissionActive ? styles.blockEvents : "")}>
                            <PostsStates error={error} posts={posts} navigate={navigate}/>
                        </div>
                </div>
            </div>
            <Submission active={submissionActive} setActive={setSubmissionActive} />
        </div>
    );
}
