import React, { Component, useState, useEffect } from 'react';

import ReactDOM from 'react-dom';


import './spotlight-search.component.scss';

import { message, Modal, Skeleton } from 'antd';

import { GlobalHotKeys } from 'react-hotkeys';

import { Location, SettingsUtil } from './../../utils/';

// import {
//     MenusAPI,
// }
//     from '../../../core/models';

let subMenu;



const SpotlightReference = React.forwardRef((props, ref) => {
    return <Spotlight {...props} ref={ref} />
})

export default SpotlightReference;


class Spotlight extends Component {

    constructor(props) {
        super(props);

        this.searchInput = React.createRef();

        this.menuItem = React.createRef();

        this.state = {
            isOpen: false,
            menus: [],
            searchText: '',
            activeMenu: {},
            searchList: [],
            querySearchList: [],
            user: props.user,
            config: props.config || [],

            matching: []
        }

        // this.openSpotlightModal();
    }

    openModal = () => {

        let menus = SettingsUtil.getMenus();

        let config = SettingsUtil.getConfig();

        this.setState({ isOpen: true, menus, config });

    }

    currentIndex = 0;


    keyboardControlMap = {
        moveUp: 'up',
        moveDown: 'down',
        enter: 'enter'
    }

    keyboardHandlers = {
        'moveUp': (event) => { this.traverse(0) },
        'moveDown': (event) => { this.traverse(1) },
        'enter': (event) => { this.onSelect(event) },
        'escape': (event) => { this.setState({ isOpen: false }) },

    }

    componentDidMount = async () => {
        // this.openSpotlightModal()
    }


    openSpotlightModal = async () => {
        const { user } = this.state;

        this.currentIndex = 0;

        if (!this.state.isOpen) {
            setTimeout(() => { this.searchInput.current.focus() }, 300);
        }

        // const result = await MenusAPI.getMenus(user);

        let menus = SettingsUtil.getMenus();



        this.setState({ isOpen: true, menus });
    }

    searchMenus = (event) => {
        let searchText = event.target.value
        this.setState({ searchText: searchText });


        // Start the search if condition matches
        // this.searchQuery(searchText);
    }

    /**
     * 
     * @param {*} query 
     */
    searchQuery = async (query) => {

        // Variable to record matching data
        let { matching = [], config } = this.state;

        config.forEach(async (condition) => {

            if (query.length >= 3) {

                const results = await condition.search(query)

                matching = [].concat(matching, results);

                this.setState({ matching })
            }
        })

        // 
    }

    advancedSearch = (searchText) => {
        {

            let obj = {};
            if (searchText.length == 10 && searchText.slice(0, 3) != "INV") {
                if (parseInt(searchText).toString().length == 10) {
                    obj = 2;
                }
                else if (/[^a-zA-Z0-9]/.test(searchText) && searchText.indexOf("-") === -1) {
                    obj = 2;
                }
                else {
                    obj = 1;
                }
            }
            else if (searchText.slice(0, 3) == "TKT") { // if the first 3 characters are tkt , its gonna be a ticket
                obj = 6;
            } else if (searchText.slice(0, 3) == "INV") {
                obj = 8;
            } else if ((parseInt(searchText).toString().length == 4 || parseInt(searchText).toString().length == 3) && parseInt(searchText).toString() != "NaN") {
                obj = 4;
            } else if (searchText.length == 11 && searchText.indexOf("-") === -1) {
                if (/\s/g.test((searchText).charAt(4))) { // check if the 4th characted is space
                    obj = 4;
                } else {
                    obj = 2;
                }
            } else if (!isNaN(searchText)) { // checking if it is a number , to check for booking id
                obj = 8;
            } else if (searchText.length == 16) {
                obj = 3;
            } else if (searchText.indexOf("-") != -1) {
                obj = 5;
            }
            // else {
            //     obj = 2;     //@ToDp : Carefully write execution for this case
            // }

            this.searchVal(obj, searchText);
        }
    }

    searchVal = async (obj, searchText) => {
        let result;
        let querySearchList = []
        let url
        let body
        switch (obj) {

            // To search PNR
            case 1:
                url = "bookingToken/" + searchText;
                result = await Get({ url: url });
                if (result.success && Object.keys(result.response).length) {
                    result.response.name = searchText;
                    result.response.url = 'booking/' + result.response.id;
                    querySearchList.push(result.response)
                    this.setState({ querySearchList });


                    Location.navigate({ url: '/booking/' + result.response.id });
                }
                break;

            // To search User
            case 2:     //@TODO MAKE A LIST PAGE WHERE WE SHOULD REDIRECT
                // getSetValue.setValue(searchText);

                url = '/searchUsers?searchText=' + searchText;
                // url = '/searchUsers';
                const queryParam = { searchText };
                Location.navigate({ url: url });
                // Location.navigate({ url, queryParam });
                break;

            // To search Payment
            case 3:     //@TODO MAKE A LIST PAGE WHERE WE SHOULD REDIRECT
                // getSetValue.setValue(searchText);

                break;

            // To search vehicle
            case 4:     //@TODO MAKE A LIST PAGE WHERE WE SHOULD REDIRECT

                url = '/searchVehicles?searchText=' + searchText;
                // url = '/searchVehicles';
                //const queryParam = { searchText };
                Location.navigate({ url: url });

                break;

            // To search coupon
            case 5:

                body = 'coupon_code="' + searchText + '"';
                result = await Get({ url: "coupon?query=" + body });
                if (result.success && result.response.length) {
                    url = '/campaign/' + result.response[0].campaign_id;
                    Location.navigate({ url: url })
                }
                break;

            // To search Ticket
            case 6:

                // url = "/ticket/" + searchText + "\"";
                // result = await Get({ url: url });

                body = 'ticket_number="' + searchText + '"';
                result = await Get({ url: "task?query=" + body });
                if (result.success && result.response.length) {
                    url = '/ticket/' + result.response[0].id;
                    Location.navigate({ url: url })
                }
                break;

            // To search Vendor
            case 7:     //@TODO MAKE A LIST PAGE WHERE WE SHOULD REDIRECT

                break;

            // To search Invoice
            case 8:

                body = 'invoice="' + searchText + '"';
                result = await Get({ url: "expenseVoucher?query=" + body });
                if (result.response.length) {
                    url = '/expenseVoucher/' + result.response[0].id;
                    Location.navigate({ url: url })
                }
                break;

            case 9:     //@TODO MAKE A LIST PAGE WHERE WE SHOULD REDIRECT

                break;

            default:
                this.setState({ querySearchList: [] })
                break;
        }
    }


    keyboardPress = (event) => {
        const { searchText } = this.state;

        var menus = document.getElementsByClassName('spotlight-menu-list')[0];

        if (event.target.value) {

            // On Clicking Down
            if (event.which == 40) {

                this.searchInput.current.blur();

                if (menus && menus.children.length) {

                    var menus = document.getElementsByClassName('spotlight-menu-list')[0];

                    if (menus) {

                        subMenu = menus.querySelectorAll('.list-group-item')[0]

                        setTimeout(() => {

                            subMenu.focus();

                        }, 10);
                        subMenu.classList.add('hovered');
                    }
                }

            } else if (event.which == 38) {

                // On Clicking Top

                this.searchInput.current.blur();
            }
            else if (event.which == 13) {

                // On Clicking Enter

                this.redirectTo(this.state.querySearchList[this.state.querySearchList.length - 1]);
                this.advancedSearch(searchText);

            } else {


            }
        }
    }

    onSelect = (event) => {
        const { searchList = [], querySearchList = [] } = this.state;
        const searchLength = searchList.length - 1;
        if (event.which == 40) {
            this.searchInput.current.blur();
            var menus = document.getElementsByClassName('spotlight-menu-list')[0];
            if (menus) {
                subMenu = menus.querySelectorAll('.list-group-item')[0]
                // subMenu.focus();
                subMenu.classList.add('hovered');
            }
        } else if (event.which == 38) {
            this.searchInput.current.blur();
        }
        else if (event.which == 13) {
            if (searchList.length)
                this.redirectTo(searchList[searchList.length - 1][this.currentIndex]);
            else if (querySearchList.length)
                this.redirectTo(searchList[searchList.length - 1][this.currentIndex]);
        }
        this.currentIndex = 0;
    }

    traverse = (direction) => {
        subMenu.classList.remove('hovered');
        if (direction) {
            if (subMenu.nextSibling) {

                this.currentIndex++;

                subMenu = subMenu.nextSibling;

                subMenu.classList.add('hovered');

                // subMenu.focus();
            } else {
                this.searchInput.current.focus()
            }
        } else {
            if (subMenu.previousSibling) {
                this.currentIndex--;
                subMenu = subMenu.previousSibling;
                subMenu.classList.add('hovered');

                // subMenu.focus();
            } else {

                this.searchInput.current.focus()
            }
        }
    }

    redirectTo = (state) => {

        this.setState({ isOpen: !this.state.isOpen });

        if (state) {
            Location.navigate({ url: state.path });
        }
    }

    render() {

        const { menus, searchText, isOpen, matching = [], config } = this.state;

        if (isOpen) {
            // document.getElementById('spotlight-input').focus();
        }

        let matches = [];

        if (searchText) {

            // 
            const { searchList = [] } = this.state

            menus.forEach((module) => {
                if (module.is_visible && module.caption && module.path && module.caption.toLowerCase().indexOf(searchText.toLowerCase()) != -1) {
                    matches.push(module)
                }
            });

            searchList.push(matches);
        }

        const autofocus = (el) => {
            const found = ReactDOM.findDOMNode(el);


            if (found && document.activeElement && document.activeElement.id !== "spotlight-input") {
                found.focus();
            }
        };


        return (
            <Modal destroyOnClose={true} className="spotlight-modal" visible={isOpen} header={null} footer={null} onCancel={() => {

                this.setState({ isOpen: false })
            }
            }>

                <GlobalHotKeys root={false} attach={window} focused={true} keyMap={this.keyboardControlMap} handlers={this.keyboardHandlers}>


                    <div className="spotlight-modal">

                        <div className="input-group">

                            <div className="input-group-prepend">
                                <span className="input-group-text" id="basic-addon1">
                                    <i className="fa fa-search"></i></span>
                            </div>

                            <input autoComplete="Off" ref={this.searchInput} id="spotlight-input" type="text" className="form-control" onKeyDown={this.keyboardPress.bind(this)} onChange={(event) => { this.currentIndex = 0; this.searchMenus(event) }} placeholder="Search accross all available menus" aria-label="Username" aria-describedby="basic-addon1" />
                        </div>

                        {/* Menus matching Text */}
                        {
                            searchText
                            // &&
                            // matches.length != 0
                            &&
                            <div className="card spotlight-menu-list">

                                <div className="list-group list-group-flush">
                                    {
                                        matches.slice(0, 10).map((match, key) => (
                                            <li
                                                // tabIndex={key}
                                                ref={this.menuItem}
                                                onKeyDown={this.onSelect}
                                                onClick={() => this.redirectTo(match)}
                                                key={key + 1}
                                                className="list-group-item">
                                                {match.caption}
                                            </li>
                                        ))

                                    }

                                    {/* Config */}
                                    {config.map((condition) => <QuerySearcher callback={() => {

                                        this.setState({ isOpen: false })

                                    }} query={searchText} config={condition} />)}
                                    {/* Config Ends */}


                                </div>

                            </div>
                        }
                        {/* Menus Ends */}




                        {/* Matching List */}
                        {/* {
                            searchText
                            &&
                            matching.length != 0 &&
                            <div className="card spotlight-menu-list">

                                <div className="list-group list-group-flush">
                                    {
                                        matching.slice(0, 10).map((match, key) => (
                                            <li
                                                // tabIndex={key}
                                                ref={this.menuItem}
                                                onKeyDown={this.onSelect}
                                                onClick={() => this.redirectTo(match)}
                                                key={key + 1}
                                                className="list-group-item">
                                                {match.label}
                                            </li>
                                        ))

                                    }
                                </div>
                            </div>
                        } */}

                        {/* Matching List ends */}


                    </div>


                </GlobalHotKeys>
            </Modal >

        )
    }
}


/**
 * Component would accept the config and search 
 */
function QuerySearcher({ config, query, callback }) {

    const [loading, setLoading] = useState(false);

    const [results, setResults] = useState([]);

    useEffect(() => {

        // Load the data
        loadData(config);

    }, [query])

    /**
     * Load the data
     */
    async function loadData(condition) {

        setLoading(true);

        const results = await condition.search(query)

        setResults(results);

        setLoading(false);
    }

    /**
     * Redirect to the element
     */
    function redirectTo(record) {

        if (record.path) {

            Location.navigate({ url: record.path });

        } else {

            message.warning('Path Missing')
        }

        callback();
    }


    function onSelect(event, record, index) {


        if (event.which == 40) {

            // this.searchInput.current.blur();

            // var menus = document.getElementsByClassName('spotlight-menu-list')[0];

            // if (menus) {
            //     subMenu = menus.querySelectorAll('.list-group-item')[0]
            //     // subMenu.focus();
            //     subMenu.classList.add('hovered');
            // }
        } else if (event.which == 38) {
            // this.searchInput.current.blur();
        }
        else if (event.which == 13) {

            redirectTo(record);

            // if (searchList.length)
            //     this.redirectTo(searchList[searchList.length - 1][this.currentIndex]);
            // else if (querySearchList.length)
            //     this.redirectTo(searchList[searchList.length - 1][this.currentIndex]);
        }
    }

    return (<>

        {
            loading
                ?
                <div className='skeleton-effect'><Skeleton /></div>
                :
                <>
                    {
                        results.map((record, index) => {

                            return (<li
                                // tabIndex={key}
                                // ref={this.menuItem}
                                onKeyDown={(event) => {

                                    onSelect(event, record, index)

                                }}
                                onClick={() => redirectTo(record)}
                                key={index + 1}
                                className="list-group-item">
                                {record.label}
                            </li>)
                        })
                    }
                </>
        }

    </>)

}