import React, {useRef, useEffect, useMemo, useState} from "react";
import {AccordionGroup, AccordionGroupItem} from "../AccordionGroup";
import {Form, Button} from "react-bootstrap";
import Mark from "mark.js";

import {ConfigRow, SectionTables} from "./types";
import {ConfigData, SectionItem, ThemeItem} from "./Data";
import {FormTable} from "./FormTable";
import {useTinyMCE} from "../../hooks/useTinyMCE";

const MIN_SEARCH_CHARS = 3;

interface Props {
    configRows: ConfigRow[];
    sectionTables: SectionTables;
    startExpanded: boolean;
}

interface SearchState {
    searchStr: string;
    toggleAll: boolean | null; // Force an accordion toggle value (expanded, collapsed, or user-controlled).
}

export const ConfigSearch = ({configRows, sectionTables, startExpanded = false}: Props) => {
    
    let [{searchStr, toggleAll}, setSearchState] = useState<SearchState>({searchStr: '', toggleAll: null});
    let [saveBtnEnabled, setSaveBtnEnabled] = useState<boolean>(false);
    
    function setToggleAll(toggle = false): void {
        setSearchState({searchStr: searchStr, toggleAll: toggle});
    }
    function setSearchKeywords(rawStr: string): void {
        let str = rawStr.trim(); 
        setSearchState({searchStr: str.length >= MIN_SEARCH_CHARS ? str : '', toggleAll: null});
    }
    useEffect(() => {
        if (startExpanded) {
            setToggleAll(true);
        }
    }, []); // Empty dependencies; Runs only on first render.
    
    useTinyMCE(editor => {
        editor.on('click', function () {
            setSaveBtnEnabled(true);
        });
    });
    
    const origData = useMemo(() => {
        return new ConfigData(configRows, sectionTables);
    }, [configRows, sectionTables]); // The computation will only re-run when `prop` changes
        
    let filteredData = useMemo<ConfigData>(() => {
        if (!searchStr) {
            return origData;
        }
        return origData.configSearch(searchStr);
    }, [origData, searchStr]);
    
    let noResultsFound = filteredData.isEmpty();

    let markerRef = useRef(new Mark(document.querySelector('.react-root')));
    
    useEffect(() => {
        // Highlight on-screen matching search strings:
        markerRef.current.unmark();
        if (!searchStr) {
            return;
        }
        markerRef.current.mark(searchStr, {"element": "mark"});     
    },[searchStr])
    
    return <>
        <input type="submit"
               name="ops_Form__UpdateConfig__AUTO_submit" 
               id="ops_Form__UpdateConfig__AUTO_submit" 
               className="ops_form_element_button ops_form_element_submit button--large" 
               value="Save changes"
               disabled={!saveBtnEnabled}
               title={saveBtnEnabled ? 'Save your changes' : 'You must modify a setting below first'}
        />
        <br/><br/>
        <div className="d-flex align-items-center">
            <Form.Control
                size="lg"
                className="flex-grow-1 me-3"
                type="text"
                placeholder="Find settings..."
                onChange={({target}) => {
                    setSearchKeywords(target.value);
                }}
            />
            <Button variant="primary" className="white-space-pre me-1" onClick={e=>setToggleAll(false)}>▲ Collapse All</Button>
            <Button variant="primary" className="white-space-pre me-1" onClick={e=>setToggleAll(true)}>▼ Expand All</Button>
        </div>
        <br/>
        <div className={["message ms-1", noResultsFound ? '' : 'd-none' ].join(' ')}>
            No results found.
        </div>
        <div className={["config-search-form", searchStr ? 'search-applied' : '', noResultsFound ? 'd-none' : ''].join(' ')}>
            <AccordionGroup itemData={filteredData.getDataStore()} toggleAll={toggleAll} itemRenderer={(theme: ThemeItem) =>
                <AccordionGroupItem 
                    eventKey={theme.header} 
                    key={theme.header}
                    header={theme.header} 
                    visible={theme.visible} 
                    toggleApplied={toggleAll !== null}
                    title={theme.header}
                >
                    <AccordionGroup itemData={theme.sections} toggleAll={toggleAll} itemRenderer={(section: SectionItem) =>
                        <AccordionGroupItem
                            header={section.header}
                            key={section.header}
                            visible={section.visible} 
                            toggleApplied={toggleAll !== null}
                            title={theme.header + ' ➔ ' + section.header}
                        >
                            <FormTable sectionItem={section} onElementClick={ ()=>setSaveBtnEnabled(true) }/>

                        </AccordionGroupItem>
                    }/>
                </AccordionGroupItem>
            }/>
        </div>
        
    </>;
}

