import { useContext, useEffect, useState } from 'react';
import TokenContextProvider from '../contexts/tokenProvider';
import { Project } from '../core/project';
import { ClientContext } from '../contexts/clientProvider';
import TokenRenderer from './TokenRenderer';
import DefaultRenderer, { RenderProps } from '../renderers/DefaultRenderer';
import { Token as BaseToken, createToken } from '../core/token';

export default function Token({
    tokenId = null,
    project = null,
    settings = {},
    customRenderer = null,
    rendererProps = {},
    className = null,
    token = null,
    loadingComponent: LoadingComponent = null,
}: {
    tokenId?: number;
    project?: Project;
    settings?: {
        useRandom?: boolean;
        assets?: number[];
        pathId?: number;
        colours?: number[];
        seed?: number;
    };
    className?: string;
    customRenderer?: typeof DefaultRenderer | DefaultRenderer;
    rendererProps?: RenderProps;
    token?: BaseToken;
    loadingComponent?: any;
}) {
    const [loaded, setLoaded] = useState(false);
    const [currentProject, setCurrentProject] = useState(null);
    const [currentTokenId, setCurrentTokenId] = useState(null);
    const [customToken, setCustomToken] = useState<BaseToken>(null);

    const client = useContext(ClientContext);

    useEffect(() => {
        if (!client.loaded) return;
        let newProject = project || client.project;
        const main = async () => {
            setLoaded(false);
            setCustomToken(null);

            if (!tokenId) setCurrentTokenId(0);
            else setCurrentTokenId(tokenId);

            if (
                settings.useRandom ||
                settings.assets ||
                settings.colours ||
                settings.pathId
            ) {
                let args: any = {};
                if (settings.useRandom) {
                    args.pathId = Math.floor(
                        Math.random() * newProject.deployedProject.paths.length
                    );

                    let assets = newProject.getAssetSections();
                    args.assets = Object.keys(assets).map((key) => {
                        let section = assets[key];
                        let asset =
                            section[
                                Math.floor(
                                    (settings?.seed ||
                                        Math.floor(Math.random() * 1000)) %
                                        section.length
                                )
                            ];

                        if (!asset) return 0;
                        return asset.assetId;
                    });
                    args.colours = [];
                }

                args.pathId =
                    settings.pathId !== undefined && settings.pathId !== null
                        ? settings.pathId
                        : args.pathId || 0;
                args.assets =
                    settings.assets &&
                    settings.assets.filter((val) => val === null).length !==
                        settings.assets.length
                        ? settings.assets.map((val) => val || 0)
                        : args.assets || [];
                args.colours = settings.colours || args.colours || [];

                setCurrentProject(newProject);
                setCustomToken(
                    token ||
                        (await createToken(
                            newProject,
                            tokenId || 0,
                            args.pathId,
                            args.assets,
                            args.colours
                        ))
                );
                setLoaded(true);
            }
        };

        main();
    }, [client, tokenId, project, settings, token]);

    return (
        <div className={className}>
            {!loaded ? (
                <>
                    {LoadingComponent ? (
                        <LoadingComponent />
                    ) : (
                        <div
                            style={{
                                textAlign: 'center',
                                padding: '12px',
                                border: '1px solid black',
                            }}
                        >
                            <h1>Loading Token</h1>
                            <small>InfinityMint</small>
                        </div>
                    )}
                </>
            ) : (
                <>
                    {currentTokenId && !customToken ? (
                        <TokenContextProvider
                            tokenId={currentTokenId}
                            project={currentProject}
                            loadingComponent={LoadingComponent}
                        >
                            <TokenRenderer
                                customRenderer={customRenderer}
                                rendererProps={rendererProps}
                            />
                        </TokenContextProvider>
                    ) : (
                        <TokenRenderer
                            customRenderer={customRenderer}
                            customToken={customToken}
                            rendererProps={rendererProps}
                        />
                    )}
                </>
            )}
        </div>
    );
}
