import * as React from 'react';
import { copyTransforms, RefinerProps } from './utils';
import { debounce } from 'lodash';

interface ChoiceState {
    id: string; // unique id for the Component
    choices: any[]; //the selected choices
}

/**
 * Column Component to add filter/refinement functionality to a categorical table column.
 */
export class ColumnChoiceRefinerComponent extends React.Component<
    RefinerProps,
    ChoiceState
> {
    protected static id_counter = 0;
    protected id;
    transformUpdateDebounced;

    constructor(props) {
        super(props);
        const state = {
            id: 'mmui_column_choice_refiner_component_' + this.getId(),
            choices: [],
        };
        this.state = state;

        // debounce updating the transforms with input value
        const delay =
            this.props.transformsDelay === undefined
                ? 1000
                : this.props.transformsDelay;
        const transformUpdateHandler = () => {
            this.updateTransforms(this.state.choices);
        };
        this.transformUpdateDebounced = debounce(transformUpdateHandler, delay);
    }

    /**
     * Generate a unique id for this component instance
     */
    protected getId(): string {
        if (this.id === undefined) {
            this.id = ColumnChoiceRefinerComponent.id_counter;
            ColumnChoiceRefinerComponent.id_counter++;
        }
        return this.id;
    }

    clearInputs = () => {
        // debounce updating the transforms with input value
        this.transformUpdateDebounced();
        document
            .querySelectorAll(`#${this.state.id} input[type=checkbox]`)
            .forEach((el: any) => (el.checked = false));

        this.setState(
            {
                choices: [],
            },
            () => {
                this.props.setIsFiltered(false);
            }
        );
    };

    /**
     * Handles changes to the input field.
     *  If there is a value in the input field, set a categorical transform with that value on config.columnName.
     * @param evt
     */
    handleInputChange(evt) {
        const value = evt.target.value;
        const checked = evt.target.checked;

        // debounce updating the transforms with input value
        this.transformUpdateDebounced();

        const selectedChoices = JSON.parse(JSON.stringify(this.state.choices));
        const choiceIndex = selectedChoices.indexOf(value);
        if (checked) {
            if (choiceIndex < 0) {
                selectedChoices.push(value);
            }
        } else {
            if (choiceIndex >= 0) {
                selectedChoices.splice(choiceIndex, 1);
            }
        }

        this.setState(
            {
                choices: selectedChoices,
            },
            () => {
                if (this.state.choices.length > 0) {
                    this.props.setIsFiltered(true);
                } else {
                    this.props.setIsFiltered(false);
                }
            }
        );
    }

    updateTransforms(choices) {
        let config = this.props.config,
            newTransforms,
            refinementTransform;
        const filters = [];
        for (let i = 0; i < choices.length; i++) {
            const filter = {
                value: choices[i],
                column: config.columnName,
                type: 'equalsTextStrict',
            };
            filters.push(filter);
        }

        // make a complete copy of the transforms
        newTransforms = copyTransforms(this.props.transforms);
        if (
            Object.prototype.hasOwnProperty.call(
                newTransforms.filters,
                config.columnName
            )
        ) {
            refinementTransform = newTransforms.filters[config.columnName];
        } else {
            refinementTransform = {
                type: 'or',
                column: config.columnName,
            };
        }

        refinementTransform.filters = filters;
        newTransforms.filters[config.columnName] = refinementTransform;

        this.props.setTransforms(newTransforms);
    }

    /**
     * Render Column Component
     */
    render() {
        const componentColumnId = this.getId();
        return (
            <React.Fragment>
                <div
                    id={this.state.id}
                    className="form-group mmui-form-group-scroll mb-0 mmui-hmx-15"
                >
                    <div className="form-group">
                        {this.props?.data?.extent.map((ex, i) => {
                            if (ex != '') {
                                const id = `${this.props.componentHeadId}-${componentColumnId}-${i}`;
                                return (
                                    <div
                                        key={id}
                                        className="form-check"
                                        title={ex}
                                    >
                                        <input
                                            className="form-check-input"
                                            id={id}
                                            type="checkbox"
                                            name={id}
                                            value={ex}
                                            onChange={this.handleInputChange.bind(
                                                this
                                            )}
                                        ></input>
                                        <label
                                            htmlFor={id}
                                            className="mt-1 form-check-label mmui-form-check-label mmui-refiner-input-label"
                                        >
                                            {ex}
                                        </label>
                                    </div>
                                );
                            }
                        })}
                    </div>
                </div>
                <div>
                    <button
                        type="button"
                        className="mmui-reset-link btn btn-link pl-0"
                        onClick={this.clearInputs}
                    >
                        Clear
                    </button>
                </div>
            </React.Fragment>
        );
    }
}
