import { notification } from 'antd';
import { isEmpty } from 'lodash';
import React, { useState, useEffect, useRef } from 'react';
import { useHistory } from "react-router-dom";
import { selectorService } from '../services/selectorService';
// import { authenticationService } from '../_services';

export const RepeatedData = React.createContext({});

const RepeatedDataProvider = ({ mathJax, children }) => {
    const history = useHistory();
    const [data, setData] = useState({queue: {
        classIsSet: false,
        subjectsAreSet: false,
        questionTypesAreSet: false,
        topicsAreSet: false
    },
    mathJax});
    const mounted = useRef();

    useEffect(() => {
        // effect
        mounted.current = true;
        getClassFromServer();
        return () => {
            // cleanup
            mounted.current = false;
        };
    }, []);

    useEffect(() => {
        if (data.queue.classIsSet && !data.queue.subjectsAreSet) {
            updateDataFromServer();
        }
        if (data.queue.subjectsAreSet && !data.queue.topicsAreSet) {
            updateTopicsFromServer();
        }
    }, [data.queue.classIsSet, data.queue.subjectsAreSet, data.queue.questionTypesAreSet]);

    async function getClassFromServer() {
        // get class
        try {
            const result = await selectorService.loadClasses();
            mounted.current && setData(prev => ({ ...prev, classes: result.result, queue: {...prev.queue, classIsSet: false} }));
            return;            
        } catch (error) {
            window.location.reload();
        }
    }

    async function updateDataFromServer() {
        try {
            // get subjects
            const subGet = await selectorService.loadSubjects("doesn't matter");
            // get questionType
            const quesGet = await selectorService.loadQuestionTypes();

            // check when all promise fullfill, save the responses to data variable.
            Promise.all([subGet, quesGet]).then((fetchedData) => {
                mounted.current && setData(prev => ({ 
                    ...prev, 
                    subjects: fetchedData[0].result || [], 
                    questionTypes: fetchedData[1].result || [],
                    queue: {
                        ...prev.queue,
                        subjectsAreSet: true,
                        questionTypesAreSet: true
                    }
                }));
            });
        } catch (error) {
            notification.error({
                message: "Something went wrong, reloading the page.",
                duration: 15
            });
            setTimeout(() => {window.location.reload()}, 2000);
        }
        // get sujbect
    }

    async function updateTopicsFromServer() {
        if(data.subjects?.length > 0) {
            // this method yielded result separately owing to the fact that the response is caught inside the mapped function.
            // const topicsFetchPromise = await Promise.all(data.subjects.map(async (subjectItem) => {
            //     const response = await selectorService.loadCategory(subjectItem.id);
            //     console.log(response);
            // }));

            // this second method is much better for catching results all gathered up into one variable.
            let topicsFetchPromise = data.subjects.map(async (subjectItem) => {
                return await selectorService.loadCategory(subjectItem.id);
            });
            Promise.all(topicsFetchPromise).then(fetchedTopic => {
                setData(prev => {
                    let newSubjectArr = prev.subjects.map((subjectItem, index) => {
                        let subObjWithTopic = {
                            ...subjectItem,
                            topics: fetchedTopic[index].status.code === "1"? fetchedTopic[index].result : []
                        }
                        return subObjWithTopic;
                    });
                    // console.log(newSubjectArr); dev-logging
                    return ({
                        ...prev, 
                        subjects: newSubjectArr, 
                        queue: {
                            ...prev.queue,
                            topicsAreSet: true
                        }
                    });
                })
            }).catch(err => console.log(err));
            // console.log(topicsFetchPromise)
        }
    }

    if (!data.classes) {
        return <div className='center-flex mt-3-0'>
            Setting up the class, please wait...
        </div>
    }

    return (
        <RepeatedData.Provider value={{ data, setData }}>
            {children}
        </RepeatedData.Provider>
    );
}

export default RepeatedDataProvider;
