/**
 * (New) Hook groups all functionalities that needs to be implemented for form
 * 
 * 
 * All the forms in the projects extending/using formUtils has superpowers to control its
 * behavior with class for controlling , visibility , mandate, validation , 
 * and change 
 * 
 * @description useFormUtils hook for controlling any form and extending it
 * @author Ashique Mohammed
 * 
 */

import { useState, useEffect } from 'react';

// 
import { prepareAndExecuteScript } from '../script.utils';

let n = 1;

/**
 * 
 * @param {*} form 
 * @param {*} formSettings 
 * @returns 
 */
const useFormUtils = (form, formSettings,preference) => {

    let [config, setConfig] = useState({ fields: {}, add_on_fields: [] });

    const [formData, setFormData] = useState({});

    const [onChangeListeners, setOnChangeListeners] = useState({});

    console.log('pre',preference);

    useEffect(() => {
        setFormData({ ...form.getFieldsValue() });
    }, [form]);

    useEffect(() => {

        // With the settings received as input we have to initialize the configuration 
        // to prepare for use in the form
        initializeConfiguration();

        return () => {

        }
    }, [])

    /**
     * Takes the preference from local storage and creates the object
     */
    function initializeConfiguration() {

        let preferences = { fields: [] };

        // if (localStorage.preferences && JSON.parse(localStorage.preferences)) {

        //     preferences = JSON.parse(localStorage.preferences);
        // }

        // let activePreference = preferences;

        // We iterate the default form settings to specifiy the field configuration 
        // for each field.

        config = prepareFields({ formSettings, preference, config, index: 'fields' });

        // formSettings.fields.forEach((field) => {

        //     // We default the field setting from the default setting
        //     config.fields[field.field] = field;

        //     // We check if there is any change in the field 
        //     activePreference.fields.forEach((item) => {

        //         if (field.field === item.field) {

        //             config.fields[field.field] = item;
        //         }

        //     });
        // })

        // If there are add on fields
        // prepareFields(formSettings, activePreference, config);

        if (preference.add_on_fields) {

            config['add_on_fields'] = {};

            try {

                preference['add_on_fields'].forEach((item) => {

                    config['add_on_fields'][item.field] = item;

                });

            } catch (error) {

            }
        }

        setConfig({ ...config });
    }

    /**
     * For the index specified , we have to consider the local storage settings 
     * over the default settings to build the config object that is used in the form
     * 
     * @param {*} formSettings 
     * @param {*} activePreference 
     * @param {*} config 
     */
    function prepareFields({ formSettings, preference, config, index }) {

        formSettings[index].forEach((field) => {

            // We default the field setting from the default setting
            config[index][field.field] = field;

            // We check if there is any change in the field 
            // config = considerPreferenceFields({ field, activePreference, config, index })
            preference[index].forEach((item) => {

                if (field.field === item.field) {

                    config[index][field.field] = item;
                }

            });
        })

        return config;
    }

    /**
     * 
     * @param {*} formSettings 
     * @param {*} activePreference 
     * @param {*} config 
     * @param {*} index 
     */
    function considerPreferenceFields({ field, activePreference, config, index }) {

        activePreference[index].forEach((item) => {

            if (field.field === item.field) {

                config[index][field.field] = item;
            }

        });

        return config;
    }

    /**
     * On change listener
     * 
     * @param {*} key 
     * @param {*} column 
     */
    const onChange = async ({ field, fieldConfiguration, values: initialValues }) => {

        // On change script
        let { onChangeScript: script } = fieldConfiguration;
        // form.registerField(column, {
        //     setValue: form.setFieldsValue,
        //     getValue: form.getFieldValue,
        // });
        // setOnChangeListeners({
        //     ...onChangeListeners,
        //     [column]: callback,
        // });

        // If there is a script assigned the field , 
        // we have to execute the script
        if (script) {

            // Before Submit of form , execute the script
            let values = await prepareAndExecuteScript({
                field,
                script,
                values: initialValues,

                // We build a new object 
                // that needs to be used within the code editor
                // we can 
                formUtils: {
                    setVisible,
                    setRequired

                }
            });

            console.log(values);

        }
    };

    /**
     * Function controls the visibilty 
     * of a column 
     * 
     * @param {*} column 
     * @param {*} visibility 
     */
    const setVisible = (column, visibility) => {

        console.log(column, visibility);

        // Toggle the visiblity of the column
        config.fields[column].visible = visibility;

        form.setFields([{ name: column, visible: visibility }]);

        setConfig({
            ...config,
            updated: ++n
        })
    };

    /**
   * Function controls the visibilty 
   * of a column 
   * 
   * @param {*} column 
   * @param {*} visibility 
   */
    const setRequired = (column, required) => {

        // Toggle the visiblity of the column
        config.fields[column].required = required;

        // form.setFields([{ name: column, visible: visibility }]);

        setConfig({
            ...config,
            updated: ++n
        })
    };

    return {
        config,
        formData,
        onChange,
        setVisible,
        setRequired
    };
};

export default useFormUtils;