import { RichTextToolbarButton } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import { registerFormatType } from '@wordpress/rich-text';
import { applyFormat } from '@wordpress/rich-text';
import { RichTextShortcut } from '@wordpress/block-editor';
import {
    BlockControls
} from '@wordpress/block-editor';
import { Toolbar, Popover } from '@wordpress/components';
import { useState } from "@wordpress/element";
import { styles } from "@wordpress/icons";
import {
    CustomSelectControl,
    SelectControl,
} from '@wordpress/components';
import { useSelect } from "@wordpress/data/build-types";
import parse from 'html-react-parser';
import apiFetch from "@wordpress/api-fetch";
import { createReduxStore, register } from '@wordpress/data';

const DEFAULT_STATE = {
    icons: {
        wordpress: {
            'star-empty': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.706 8.646a.25.25 0 0 1-.188.137l-4.626.672a.25.25 0 0 0-.139.427l3.348 3.262a.25.25 0 0 1 .072.222l-.79 4.607a.25.25 0 0 0 .362.264l4.138-2.176a.25.25 0 0 1 .233 0l4.137 2.175a.25.25 0 0 0 .363-.263l-.79-4.607a.25.25 0 0 1 .072-.222l3.347-3.262a.25.25 0 0 0-.139-.427l-4.626-.672a.25.25 0 0 1-.188-.137l-2.069-4.192a.25.25 0 0 0-.448 0L9.706 8.646zM12 7.39l-.948 1.921a1.75 1.75 0 0 1-1.317.957l-2.12.308 1.534 1.495c.412.402.6.982.503 1.55l-.362 2.11 1.896-.997a1.75 1.75 0 0 1 1.629 0l1.895.997-.362-2.11a1.75 1.75 0 0 1 .504-1.55l1.533-1.495-2.12-.308a1.75 1.75 0 0 1-1.317-.957L12 7.39z"/></svg>'
        }
    },
};

const actions = {
    setIcons( icons ) {
        return {
            type: 'SET_ICONS',
            icons,
        };
    },
    getIcons( path ) {
        return {
            type: 'GET_ICONS',
            path,
        };
    },
};

const reducer = ( state = DEFAULT_STATE, action ) => {
    switch ( action.type ) {
        case 'SET_ICONS': {
            return {
                ...state,
                icons: action.icons,
            };
        }
        default: {
            return state;
        }
    }
};

const selectors = {
    getIcons( state ) {
        const { icons } = state;
        return icons;
    },
};

const controls = {
    GET_ICONS( action ) {
        return apiFetch( { path: action.path } );
    },
};

const resolvers = {
    * getIcons() {
        const icons = yield actions.getIcons( '/blockify/v1/icons/' );
        return actions.setIcons( icons );
    },
};

register( createReduxStore( 'blockify/icons', {
    reducer,
    actions,
    selectors,
    controls,
    resolvers,
} ) );

registerFormatType( 'blockify/icon', {
    title: __( 'Icon', 'blockify' ),
    tagName: 'span',
    className: 'has-icon',
    attributes: {
        style: 'style',
        class: 'class',
    },
    edit: ( { isActive, value, onChange } ) => {
        let { icons } = useSelect( select => {
            const iconData: any = select( 'blockify/icons' );

            return {
                icons: iconData.getIcons(),
            };
        }, [] ) ?? DEFAULT_STATE;

        const [ icon, setIcon ]       = useState( 'star-empty' );
        const [ iconSet, setIconSet ] = useState( 'wordpress' );
        const [ isOpen, setIsOpen ]   = useState( false );

        let iconSetOptions = [];
        let iconOptions    = {};

        Object.keys( icons ).forEach( set => {
            let label = set.split( '-' ).join( ' ' );

            label = 'wordpress' === label ? 'WordPress' : label;

            iconSetOptions.push( {
                label: label,
                value: set,
            } );

            iconOptions[set] = [];

            Object.keys( icons[set] ).forEach( iconName => {
                if ( iconName !== icon ) {
                    iconOptions[set].push( {
                        name: parse( icons[set][iconName] ),
                        key: iconName,
                    } );
                }
            } );

            if ( icons?.[iconSet]?.[icon] ) {
                iconOptions[set].unshift( {
                    name: parse( icons[iconSet][icon] ),
                    key: icon,
                } );
            }
        } );

        return (
            <BlockControls>
                <RichTextShortcut
                    type={ 'primary' }
                    character={ 'g' }
                />
                <RichTextToolbarButton
                    icon={ styles }
                    title={ __( 'Gradient', 'blockify' ) }
                    isActive={ isActive }
                    shortcutType={ 'primary' }
                    shortcutCharacter={ 'g' }
                    onClick={ () => setIsOpen( ! isOpen ) }
                />
                { isOpen &&
				  <Toolbar className={ 'blockify-components-toolbar' }>
					  <Popover
						  position={ 'bottom center' }
						  className={ 'blockify-gradient-text-control' }
						  focusOnMount={ 'container' }
						  onFocusOutside={ () => setIsOpen( false ) }
					  >
						  <SelectControl
							  label={ __( 'Select Icon Set', 'blockify' ) }
							  value={ iconSet }
							  options={ iconSetOptions }
							  onChange={ newIconSet => {
                                  setIconSet( newIconSet );

                                  onChange( applyFormat( value, {
                                      type: 'blockify/icon',
                                      attributes: {
                                          class: 'has-gradient-text ' + 'icon-set-' + newIconSet
                                      }
                                  } ) )
                              } }
						  />

						  <CustomSelectControl
							  label={ __( 'Select Icon', 'blockify' ) }
							  options={ iconOptions?.[iconSet] ?? DEFAULT_STATE }
							  value={ icons?.[iconSet]?.[icon] }
							  className={ 'blockify-icon-setting' }
							  onChange={ newIcon => {
                                  setIcon( newIcon );

                                  onChange( applyFormat( value, {
                                      type: 'blockify/icon',
                                      attributes: {
                                          class: 'has-gradient-text ' + 'icon-' + newIcon
                                      }
                                  } ) )
                              } }
						  />
					  </Popover>
				  </Toolbar>
                }
            </BlockControls>
        );
    }
} );


