import React, { Suspense, useEffect, useState } from 'react';
import { __ } from '@wordpress/i18n';
import { head, is, isEmpty, isNil, uniq } from 'ramda';

// store
import { storeGet, useStoreValue } from '../../../../../../store';

// tools
import renderHtmlContent from '../../../../../../helpers/renderHtmlContent';

// components
import ElementSettingRepeater from '../ElementSettingRepeater';
import { InputText } from 'primereact/inputtext';
import { MultiSelect } from 'primereact/multiselect';
import { Editor } from 'primereact/editor';
import ElementSettingTableColumns from '../ElementSettingTableColumns';
import { InputSwitch } from 'primereact/inputswitch';
import ElementSettingChips from '../ElementSettingChips';
import ElementSettingCriteriaTableColumns from '../ElementSettingCriteriaTableColumns';
import ElementSettingTableColumnsForCsv from '../ElementSettingTableColumnsForCsv';
import { mimeTypes } from '../../../../../../configData';
import ElementSettingReportHeader from '../ElementSettingReportHeader';
import ElementSettingReportEnable from '../ElementSettingReportEnable';
import getTokens from '../../../../../../helpers/getTokens';

const ElementSettingSpreadsheet = React.lazy(() => import('../ElementSettingSpreadsheet'));


const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus, context, required, hasError }) => {
    const [existingVars, setExistingVars] = useState([]);
    const documentCategories = useStoreValue('documentCategories');

    const settingLabels = {
        label: __('Label', 'gepafin'),
        placeholder: __('Segnaposto', 'gepafin'),
        step: __('Numero Decimali', 'gepafin'),
        isRequestedAmount: __('Importo richiesto', 'gepafin'),
        isDelegation: __('Delega', 'gepafin'),
        isPecEmail: __('PEC email', 'gepafin'),
        options: __('Opzioni', 'gepafin'),
        mime: __('Tipo di file', 'gepafin'),
        documentCategories: __('Categorie dei documenti', 'gepafin'),
        text: __('Testo formattato', 'gepafin'),
        table_columns: '',
        criteria_table_columns: '',
        variable: __('Variabile (lettere, cifre e "_"; il primo carattere deve essere una lettera!)', 'gepafin'),
        formula: __('Formula di calcolo automatico', 'gepafin'),
        isChecklistItem: __('Fa parte di "checklist"?', 'gepafin'),
        reportEnable: __('Aggiungere nel report CSV?', 'gepafin'),
        reportHeader: __('Nome della colonna nel CSV', 'gepafin'),
        reportColumns: __('', 'gepafin'),
        template: __('Template foglio', 'gepafin')
    }

    const settingDescription = {
        formula: __('Crea una formula usando variabili dichiarate in precedenza. Utilizza questi operatori matematici: <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>. Esempio: <code>{entrate}+{assicurazione}</code>.', 'gepafin')
    }

    const renderHeader = () => {
        return (
            <span className="ql-formats">
                <button className="ql-bold" aria-label="Bold"></button>
                <button className="ql-italic" aria-label="Italic"></button>
                <button className="ql-underline" aria-label="Underline"></button>
                <button className="ql-link" aria-label="Link"></button>
                <button className="ql-list" value="ordered"></button>
                <button className="ql-header" value="2"></button>
                <button className="ql-header" value="3"></button>
                <button className="ql-blockquote"></button>
                <button className="ql-list" value="bullet"></button>
                <button className="ql-indent" value="-1"></button>
                <button className="ql-indent" value="+1"></button>
            </span>
        );
    };

    const header = renderHeader();

    const invalidFormula = (value) => {
        try {
            getTokens(value)
            return false;
        } catch {
            return __('Potrebbe essere un errore nella formula!')
        }
    }

    const getProperField = (setting) => {
        if (setting.name === 'options') {
            return <ElementSettingRepeater
                value={is(Array, setting.value) ? setting.value : []}
                name={setting.name}
                bandoStatus={bandoStatus}
                setDataFn={updateDataFn}/>
        } else if (setting.name === 'mime') {
            return <MultiSelect
                value={is(Array, setting.value) ? setting.value : []}
                onChange={(e) => updateDataFn(setting.name, e.value)}
                options={mimeTypes}
                optionLabel="name"
                display="chip"
                placeholder={__('Scegli', 'gepafin')}/>
        } else if (setting.name === 'documentCategories') {
            return <MultiSelect
                value={is(Array, setting.value) ? setting.value : []}
                onChange={(e) => updateDataFn(setting.name, e.value)}
                options={documentCategories}
                display="chip"
                placeholder={__('Scegli', 'gepafin')}/>
        } else if (setting.name === 'text') {
            return <div translate="no"><Editor
                value={setting.value}
                headerTemplate={header}
                onTextChange={(e) => changeFn(e.htmlValue, setting.name)}
                style={{ height: 80 * 4 }}
            /></div>
        } else if (setting.name === 'step') {
            return <InputText id={setting.name}
                              keyfilter="int"
                              aria-describedby={`${setting.name}-help`}
                              placeholder="0"
                              value={setting.value}
                              onChange={(e) => changeFn(e.target.value, setting.name)}/>
        } else if (setting.name === 'table_columns') {
            return <ElementSettingTableColumns
                value={is(Object, setting.value) ? setting.value : {}}
                name={setting.name}
                bandoStatus={bandoStatus}
                setDataFn={updateDataFn}/>
        } else if (setting.name === 'criteria_table_columns') {
            return <ElementSettingCriteriaTableColumns
                value={is(Object, setting.value) ? setting.value : {}}
                name={setting.name}
                bandoStatus={bandoStatus}
                setDataFn={updateDataFn}/>
        } else if (['isRequestedAmount', 'isDelegation', 'isPecEmail', 'isChecklistItem'].includes(setting.name)) {
            return <InputSwitch
                checked={setting.value}
                onChange={(e) => changeFn(e.value, setting.name)}/>
        } else if (['reportEnable'].includes(setting.name)) {
            return <ElementSettingReportEnable setting={setting} setDataFn={updateDataFn}/>
        } else if (setting.name === 'reportColumns') {
            return <ElementSettingTableColumnsForCsv
                value={is(Object, setting.value) ? setting.value : {}}
                name={setting.name}
                bandoStatus={bandoStatus}
                setDataFn={updateDataFn}/>
        } else if (setting.name === 'reportHeader') {
            return <ElementSettingReportHeader setting={setting} changeFn={changeFn}/>
        } else if (['variable'].includes(setting.name)) {
            return <ElementSettingChips
                restrictedValues={[]}
                changeFn={(value) => changeFn(value, setting.name)}
                value={setting.value}/>
        } else if (setting.name === 'table_columns') {
            return <ElementSettingTableColumns
                value={is(Object, setting.value) ? setting.value : {}}
                name={setting.name}
                bandoStatus={bandoStatus}
                setDataFn={updateDataFn}/>
        } else if (setting.name === 'template') {
            return <Suspense fallback={null}>
                <ElementSettingSpreadsheet
                    value={setting.value}
                    name={setting.name}
                    context={context}
                    setDataFn={updateDataFn}/>
            </Suspense>;
        } else if (setting.name === 'formula') {
            const isInvalid = invalidFormula(setting.value);
            return <>
                <InputText id={setting.name} aria-describedby={`${setting.name}-help`}
                              value={setting.value}
                              onChange={(e) => changeFn(e.target.value, setting.name)}/>
                <p style={{margiTop: 0, fontSize: '14px', color: '#df3636'}}>{isInvalid}</p>
                </>
        } else {
            return <InputText id={setting.name} aria-describedby={`${setting.name}-help`}
                              className={hasError ? 'p-invalid' : undefined}
                              value={setting.value}
                              onChange={(e) => changeFn(e.target.value, setting.name)}/>
        }
    }

    useEffect(() => {
        const elements = storeGet('formElements');
        const activeElement = storeGet('activeElement');
        const vars = elements
            .filter(o => o.id !== activeElement)
            // eslint-disable-next-line
            .map((o) => {
                const variableSetting = head(o.settings.filter(s => s.name === 'variable'));
                if (variableSetting) {
                    return variableSetting.value[0];
                }
            })
            .filter(v => !isNil(v));

        setExistingVars(uniq(vars));
    }, []);

    return <div className="formElementSettings__field" key={setting.name}>
        <label htmlFor={setting.name}>
            {settingLabels[setting.name]}
            {required ? <span style={{ color: 'red', marginLeft: '4px' }}>*</span> : null}
        </label>
        {getProperField(setting)}
        {setting.name === 'label' && hasError
            ? <small className="p-error">{__('Label è obbligatoria quando è impostata una validazione.', 'gepafin')}</small>
            : null}
        {setting.name === 'formula' && !isEmpty(existingVars)
            ? <div className="formElementSettings__fieldVarsList">
                <p>Existing variables: {existingVars.map(v => <code key={v}>{`{${v}}`}</code>)}</p>
            </div> : null}
        {settingDescription[setting.name]
            ? <div className="formElementSettings__fieldDescription">
                <p>{renderHtmlContent(settingDescription[setting.name])}</p>
            </div> : null}
    </div>
}

export default ElementSetting;