/**
 * Layouts Provider for the Layout Block.
 *
 * Provides layouts, sections, and favorites to other components
 * using React's Context API.
 */

import React, { createContext, Component } from 'react';

const { apiFetch } = wp;

export const LayoutsContext = createContext( {
	favorites: '',
	favoriteKeys: '',
	layouts: '',
	sections: '',
	all: '',
	reusableBlocks: '',
	collections: '',
} );

export default class LayoutsProvider extends Component {
	state = {
		favorites: '',
		favoriteKeys: '',
		layouts: '',
		sections: '',
		all: '',
		reusableBlocks: '',
		collections: '',
	};

	/**
	 * Retrieves the keys of current user's favorites.
	 */
	getFavoriteKeys() {
		return apiFetch( {
			path: '/genesisblocks/v1/layouts/favorites',
			method: 'GET',
		} )
			.then( ( favorite_keys ) => {
				return favorite_keys;
			} )
			.catch( ( error ) => console.error( error ) );
	}

	/**
	 * Returns the current user's favorite layouts and sections.
	 */
	getFavorites() {
		return apiFetch( {
			path: '/genesisblocks/v1/layouts/favorites',
			method: 'GET',
		} )
			.then( ( favorite_keys ) => {
				const favorites = [];

				Object.values( this.state.all ).forEach( function ( item ) {
					if ( favorite_keys.includes( item.key ) ) {
						favorites.push( item );
					}
				} );

				return favorites;
			} )
			.catch( ( error ) => console.error( error ) );
	}

	/**
	 * Adds a layout to the user's favorites.
	 *
	 * @param {string} key The layout's unique key.
	 * @return {Object} The user's favorite layouts.
	 */
	addFavorite( key ) {
		return apiFetch( {
			path: '/genesisblocks/v1/layouts/favorites',
			method: 'PATCH',
			body: JSON.stringify( { genesis_blocks_favorite_key: key } ),
			_wpnonce: wpApiSettings.nonce,
		} ).catch( ( error ) => console.error( error ) );
	}

	/**
	 * Removes a layout from the user's favorites.
	 *
	 * @param {string} key The layout's unique key.
	 * @return {Object} The user's favorite layouts.
	 */
	removeFavorite( key ) {
		return apiFetch( {
			path: '/genesisblocks/v1/layouts/favorites',
			method: 'DELETE',
			body: JSON.stringify( { genesis_blocks_favorite_key: key } ),
			_wpnonce: wpApiSettings.nonce,
		} ).catch( ( error ) => console.error( error ) );
	}

	async componentDidMount() {
		const favoriteKeys = await this.getFavoriteKeys();

		/**
		 * Retrieve all the registered layouts, sections,
		 * and the user's favorites and save them to state.
		 */
		wp.apiFetch( {
			method: 'GET',
			path: '/genesisblocks/v1/layouts/all?filter=allowed',
		} ).then( async ( components ) => {
			const layouts = [];
			const sections = [];
			const reusableBlocks = [];
			const favorites = [];
			const collections = [];

			Object.values( components ).forEach( function ( item ) {
				if ( 'layout' === item.type ) {
					layouts.push( item );
				}

				if ( 'section' === item.type ) {
					sections.push( item );
				}

				if ( 'wp_block' === item.type ) {
					reusableBlocks.push( item );
				}

				if ( item.hasOwnProperty( 'collection' ) ) {
					if (
						! collections.hasOwnProperty( item.collection.slug )
					) {
						collections[ item.collection.slug ] = [];
						item.collection.image = item.image;
						collections[ item.collection.slug ] = item.collection;
					}
				}

				if ( favoriteKeys.includes( item.key ) ) {
					favorites.push( item );
				}
			} );

			this.setState( {
				all: components,
				layouts,
				sections,
				favorites,
				favoriteKeys,
				reusableBlocks,
				collections,
			} );
		} );
	}

	render() {
		if ( this.state.all ) {
			return (
				<LayoutsContext.Provider
					value={ {
						favorites: this.state.favorites,
						favoriteKeys: this.state.favoriteKeys,
						layouts: this.state.layouts,
						sections: this.state.sections,
						all: this.state.all,
						reusableBlocks: this.state.reusableBlocks,
						collections: this.state.collections,
						toggleFavorite: async ( key ) => {
							let favoriteKeys = await this.getFavoriteKeys();

							if ( favoriteKeys.includes( key ) ) {
								favoriteKeys = await this.removeFavorite( key );
							} else {
								favoriteKeys = await this.addFavorite( key );
							}

							const favorites = await this.getFavorites();

							this.setState( {
								favorites,
								favoriteKeys,
							} );

							return favorites;
						},
					} }
				>
					{ this.props.children }
				</LayoutsContext.Provider>
			);
		}
		return null;
	}
}
