import AppContext from "../contexts/AppContext";
import Header from "./App/Header";
import List from "./App/List";
import Placeholder from "./App/Placeholder";
import Form from "./App/Form";

import {base64Encode, getIdParam, removeIdParam, useMounted} from "../includes/functions";

const {Spinner} = wp.components;
const {useEffect, useState, useRef} = React;

export default function App() {
    const isAddNew = false;

    const [initialized, setInitialized] = useState(isAddNew);
    const [players, setPlayers] = useState([]);
    const [edit, setEdit] = useState(isAddNew ? -1 : null);
    const [updating, setUpdating] = useState(false);

    const [perPage, setPerPage] = useState(localStorage.getItem('radio_player_list_per_page') || 10);
    const [sortBy, setSortBy] = useState(localStorage.getItem('radio_player_list_sort_by') || 'created_at');
    const [sortOrder, setSortOrder] = useState(localStorage.getItem('radio_player_list_sort_order') || 'desc');

    const [page, setPage] = useState(1);
    const [total, setTotal] = useState(0);

    const initData = {
        id: '',

        title: wp.i18n.__('Player Title', 'radio-player'),
        sticky: false,
        status: true,
        skin: 'skin1',

        stations: [{
            title: wp.i18n.__('Station Title', 'radio-player'),
            stream: '',
            thumbnail: radioPlayer.plugin_url + '/assets/images/placeholder.png',
        }],
        autoplay: false,
        popup_icon: false,
        playlist_icon: !!radioPlayer.isPro,
        volume_control: true,
        player_status: true,
        show_artist: !!radioPlayer.isPro,
        show_artwork: !!radioPlayer.isPro,
        player_text: wp.i18n.__('Listen Live', 'radio-player'),

        width: 350,
        width_mobile: 320,
        border_radius: 10,
        bg_color: 'linear-gradient(-225deg, #E3FDF5 0%, #FFE6FA 100%)',
        bg_image: `${radioPlayer.plugin_url}/assets/images/player-bg.png`,
        bg_type: 'color',
        color_type: 'solid',
        text_color: '',
    }

    const prevDataRef = useRef(initData);

    const [editData, setEditData] = useState(initData);
    const [isDirty, setIsDirty] = useState(false);

    const getPlayers = () => {
        setInitialized(false);

        return wp.ajax
            .post('rp_get_players', {
                page,
                per_page: perPage,
                sort_by: sortBy,
                sort_order: sortOrder,
                nonce: radioPlayer.nonce,
            })
            .done(({players, total}) => {
                setTotal(total);
                setPlayers(players);
            })
            .fail((error) => console.log(error))
            .always(() => setInitialized(true));
    }

    // Get Players on mount
    useEffect(() => {
        if (isAddNew) return;

        getPlayers().then(() => {
            if (getIdParam()) {
                setEdit(getIdParam());
            }
        });

    }, []);

    const isMounted = useMounted();

    // Update editData
    useEffect(() => {
        if (!isMounted) return;

        if (!edit) {
            return;
        }

        if (edit == '-1') {
            setEditData(initData);
            return;
        }

        const editData = {...players.find(item => item.id == edit)['config'], id: parseInt(edit)}
        setEditData(editData);

        prevDataRef.current = editData;

    }, [edit]);

    // Update page title on edit
    useEffect(() => {
        if (edit) {
            if (edit < 1) {
                document.title = wp.i18n.__('Add New Player - Radio Player', 'radio-player');
            } else {
                document.title = wp.i18n.__('Edit Player', 'radio-player') + ' - ' + editData.title;
            }
        } else {
            document.title = wp.i18n.__('All Players - Radio Player', 'radio-player');
        }
    }, [edit, editData]);

    // Handle Push State Change
    useEffect(() => {
        const currentUrl = window.location.href;

        const handleLocationChange = () => {

            if (currentUrl.includes("#add-new")) {
                setEdit(-1);
            } else {
                const url = new URL(currentUrl);
                const id = url.searchParams.get('id');

                if (id) {
                    setEdit(id);
                } else {
                    setEdit(false);
                }
            }

        }

        if (currentUrl.includes("#add-new")) {
            handleLocationChange();
        }

        window.addEventListener('popstate', handleLocationChange);

        // clean up function
        return () => {
            window.removeEventListener('popstate', handleLocationChange);
        }

    }, []); // empty dependency array so this effect runs once on mount and clean up on unmount

    // Handle Pagination
    useEffect(() => {
        if (!isMounted) return;

        getPlayers();

        // smooth scroll to top
        window.scrollTo({top: 0, behavior: "smooth"});

    }, [page, perPage]);

    // Handle Sorting
    useEffect(() => {
        if (!isMounted) return;

        getPlayers();

        // smooth scroll to top
        window.scrollTo({top: 0, behavior: "smooth"});

    }, [sortBy, sortOrder]);

    // Update Player
    const updatePlayer = (playerData, isBack = false, openPreview = false) => {

        setUpdating(true);

        return wp.ajax
            .post('rp_update_player', {
                data: base64Encode(JSON.stringify(playerData)),
                nonce: radioPlayer.nonce,
            })
            .done((response) => {

                prevDataRef.current = {...playerData};

                setEditData(data => ({...data, id: parseInt(response.id)}));

                if (playerData.id) {
                    const index = players.findIndex(item => item.id == response.id);

                    players[index] = {...players[index], ...response};

                    setPlayers(players);
                } else {
                    setPlayers(prevState => [{...response, id: parseInt(response.id)}, ...prevState]);
                }

                if (openPreview) {
                    window.open(radioPlayer.site_url + `?radio_player=${response.id}&preview=1`);
                }

                Swal.fire({
                    title: wp.i18n.__("Updated!", "radio-player"),
                    text: wp.i18n.__("Player has been updated.", "radio-player"),
                    icon: 'success',
                    timer: 2000,
                    showConfirmButton: false,
                    toast: true,
                    position: 'top-end',
                    customClass: {
                        container: 'radio-player-swal radio-player-swal-toast',
                    }
                });

            })
            .fail(error => {
                console.log(error);

                Swal.fire({
                    title: wp.i18n.__("Error!", "radio-player"),
                    text: wp.i18n.__("Something went wrong.", "radio-player"),
                    icon: 'error',
                    timer: 2000,
                    showConfirmButton: false,
                    toast: true,
                });
            })
            .always(() => {
                setUpdating(false);

                if (isBack) {
                    removeIdParam();
                    setEdit(false);
                }
            });

    }

    // Delete Player
    const deletePlayer = id => {

        if (!id) {
            id = edit;
        }

        return wp.ajax
            .post('rp_delete_player', {
                id,
                nonce: radioPlayer.nonce,
            })
            .done(() => {
                removeIdParam();
                setPlayers(players => players.filter(item => item.id != id));
                setEdit(false);

                Swal.fire({
                    title: wp.i18n.__("Deleted!", "radio-player"),
                    text: wp.i18n.__("Player has been deleted.", "radio-player"),
                    icon: 'success',
                    timer: 2000,
                    showConfirmButton: false,
                    toast: true,
                    position: 'top-end',
                    customClass: {
                        container: 'radio-player-swal radio-player-swal-toast',
                    }
                });

            })
            .fail(error => {
                console.log(error);
            });
    }

    // Check if is changed
    useEffect(() => {
        if (!isMounted) return;

        const isChanged = JSON.stringify(editData) !== JSON.stringify(prevDataRef.current);
        setIsDirty(isChanged);

    }, [editData, prevDataRef.current]);

    return (
        <AppContext.Provider value={{
            edit,
            players,
            setEdit,
            editData,
            setEditData,
            updatePlayer,
            deletePlayer,
            getPlayers,
            updating,
            total,
            perPage,
            setPerPage,
            sortBy,
            setSortBy,
            sortOrder,
            setSortOrder,
            page,
            setPage,
            isDirty,
        }}>
            <div className="radio-player-app">

                <Header/>

                {!initialized && <div className="loading-spinner"><Spinner/></div>}

                {initialized && !edit && !players.length && <Placeholder setEdit={setEdit}/>}
                {initialized && !edit && !!players.length && <List/>}
                {initialized && !!edit && <Form/>}

            </div>
        </AppContext.Provider>
    )
}