/**
 * components/LinkOptionsModal.js
 *
 * @file Provides a "Link options" modal component that allows the user to edit a link
 *
 * @author Jessie Hildebrandt
 */

/* -------------------------------------------------------------------------- */
/* Local module imports */

import { LinkOptionsModal as Controller } from '../controllers/LinkOptionsModal.js';

/* -------------------------------------------------------------------------- */
/* Helper functions */

/* ---------------------------------- */
/* controlClassFromFieldState */

/**
 * Return the appropriate CSS class name for a control element to reflect `fieldState`
 *
 * @param {string} fieldState - The state of the field wrapped by the control element
 *
 * @returns {?string} The CSS class name for the control element
 */
function controlClassFromFieldState( fieldState )
{
    switch( fieldState )
    {
        case Controller.FIELD_STATE.VALIDATING:
        return 'is-loading';
        default:
        return null;
    }
}

/* ---------------------------------- */
/* inputClassFromFieldState */

/**
 * Return the appropriate CSS class name for an input element to reflect `fieldState`
 *
 * @param {string} fieldState - The state of the field wrapped by the input element
 *
 * @returns {?string} The CSS class name for the input element
 */
function inputClassFromFieldState( fieldState )
{
    switch( fieldState )
    {
        case Controller.FIELD_STATE.VALID:
        return 'is-success';
        case Controller.FIELD_STATE.INVALID:
        return 'is-danger';
        default:
        return null;
    }
}

/* ---------------------------------- */
/* abbreviateNumber */

/**
 * Abbreviate `number` to three significant digits and attach a single character suffix representing magnitude.
 *
 * @param {number} number - The number to abbreviate
 *
 * @returns {string} The abbreviated number
 */
function abbreviateNumber( number )
{
    if ( number === 0 ) return 0;
    const suffixes = [ '', 'k', 'm', 'b', 't', 'q' ];
    const magnitude = Math.floor( Math.log( number ) / Math.log( 1000 ) )
    let smallNumber = ( number / Math.pow( 1000, magnitude ) );
    smallNumber = magnitude > 0 ? smallNumber.toPrecision( 3 ) : smallNumber;
    return smallNumber + suffixes[ magnitude ];
}

/* -------------------------------------------------------------------------- */
/* Component implementation */

const LinkOptionsModal = {

    /* ---------------------------------- */
    /* oninit */

    /**
     * Called when the component is initialized
     *
     * @param {m.Vnode} vnode - The Vnode representing the component
     */
    oninit: ( { attrs } ) => {
        Controller.init();
        Controller.load( attrs.linkID );
    },

    /* ---------------------------------- */
    /* onremove */

    /**
     * Called before component element is removed from the DOM
     */
    onremove: () => {
        Controller.reset();
    },

    /* ---------------------------------- */
    /* view */

    /**
     * Called whenever the component is drawn
     *
     * @returns {m.Vnode} - The Vnode or Vnode tree to be rendered
     */
    view: ( { attrs } ) => {
        return m( '.LinkOptionsModal.modal-card', [
            m( 'header.modal-card-head', [
                m( 'p.modal-card-title', 'Link options' ),
                m( 'button.delete', {
                    disabled: Controller.isWaiting,
                    onclick: Controller.close
                } )
            ] ),
            m( 'section.modal-card-body', [
                m( '.field', [
                    m( '.control.has-icons-left', [
                        m( 'input.input', {
                            type: 'text',
                            readonly: true,
                            value: attrs.linkID,
                            onclick: ( event ) => event.currentTarget.select()
                        } ),
                        m( 'span.icon.is-left', [
                            m( 'i.fa.fa-tag' )
                        ] )
                    ] )
                ] ),
                m( '.field', [
                    m( '.control.has-icons-left', {
                        class: controlClassFromFieldState( Controller.linkDestState ) || Controller.isWaiting ? 'is-loading' : null
                    }, [
                        m( 'input.input', {
                            class: inputClassFromFieldState( Controller.linkDestState ),
                            disabled: Controller.isWaiting,
                            type: 'text',
                            placeholder: 'Destination',
                            value: Controller.linkDest,
                            oninput: ( event ) => Controller.updateLinkDest( event.target.value ),
                            onkeydown: ( event ) => {
                                if ( Controller.canRedirect() && event.key === 'Enter' )
                                {
                                    Controller.tryRedirect( attrs.linkID );
                                }
                            }
                        } ),
                        m( 'span.icon.is-left', [
                            m( 'i.fa.fa-link' )
                        ] )
                    ] )
                ] ),
                m( '.field.has-text-centered', [
                    m( 'small.has-text-grey', [
                        'This link has been visited ',
                        m( 'span.visit-counter.has-text-dark', abbreviateNumber( Controller.visitCount ) ),
                        ` time${ Controller.visitCount === 1 ? '' : 's' }`
                    ] )
                ] ),
                m( '.field.is-grouped.is-justify-content-center', [
                    m( '.control', [
                        m( 'button.button.is-danger.is-outlined', {
                            disabled: Controller.isWaiting,
                            onclick: () => Controller.openDeleteModal( attrs.linkID )
                        }, 'Delete link' )
                    ] ),
                    m( '.control', [
                        m( 'button.button.is-link.is-outlined', {
                            class: Controller.isWaiting ? 'is-loading' : null,
                            disabled: Controller.isLoading || Controller.isWaiting || !Controller.canRedirect(),
                            onclick: () => {
                                if ( Controller.canRedirect() )
                                {
                                    Controller.tryRedirect( attrs.linkID );
                                }
                            }
                        }, 'Redirect link' )
                    ] )
                ] )
            ] )
        ] );
    }

}

/* -------------------------------------------------------------------------- */
/* Export */

export { LinkOptionsModal };
