//import { init, search } from './lunr-adapter.js';
import { init, search } from './orama-adapter.js';

(function(){

window.relearn = window.relearn || {};

window.relearn.executeInitialSearch =
function executeInitialSearch(){
    if( window.relearn.isSearchInterfaceReady && window.relearn.isSearchEngineReady ){
        var input = document.querySelector('#R-search-by-detail');
        if( !input ){
            return;
        }
        var value = input.value;
        executeSearch( value );
    }
}

window.relearn.executeTriggeredSearch =
function executeTriggeredSearch(){
    var input = document.querySelector('#R-search-by-detail');
    if( !input ){
        return;
    }
    var value = input.value;
    executeSearch( value );

    // add a new entry to the history after the user
    // changed the term; this does not reload the page
    // but will add to the history and update the address bar URL
    var url = new URL( window.location );
    var oldValue = url.searchParams.get( 'search-by' );
    if( value != oldValue ){
        var state = window.history.state || {};
        state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
        url.searchParams.set( 'search-by', value );
        state.search = url.toString();
        // with normal pages, this is handled by the 'pagehide' event, but this
        // doesn't fire in case of pushState, so we have to do the same thing
        // here, too
        state.contentScrollTop = +elc.scrollTop;
        window.history.pushState( state, '', url );
    }
}

function executeHistorySearch( event ){
    // restart search if browsed through history
    if( event.state ){
        var state = window.history.state || {};
        state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
        if( state.search ) {
            var url = new URL( state.search );
            if( url.searchParams.has('search-by') ){
                var search = url.searchParams.get( 'search-by' );

				// we have to insert the old search term into the inputs
                var inputs = document.querySelectorAll( 'input.search-by' );
                inputs.forEach( function( e ){
                    e.value = search;
                    var event = document.createEvent( 'Event' );
                    event.initEvent( 'input', false, false );
                    e.dispatchEvent( event );
                });

				// recreate the last search results and eventually
				// restore the previous scrolling position
                executeSearch( search );
            }
        }
    }
}

function executeSearch( value ) {
    var input = document.querySelector('#R-search-by-detail');
    function resolvePlaceholders( s, args ) {
        var args = args || [];
        // use replace to iterate over the string
        // select the match and check if the related argument is present
        // if yes, replace the match with the argument
        return s.replace(/{([0-9]+)}/g, function (match, index) {
            // check if the argument is present
            return typeof args[index] == 'undefined' ? match : args[index];
        });
    };

    var results = document.querySelector('#R-searchresults');
    var hint = document.querySelector('.searchhint');
    hint.innerText = '';
    results.textContent = '';
    (async function(){
        var a = await search( value );
        if( a.length ){
            hint.innerText = resolvePlaceholders( window.T_N_results_found, [ value, a.length ] );
            a.forEach( function(item){
                var page = item.page;
                var context = [];
                if( item.matches ){
                    var numContextWords = 10;
                    var contextPattern = '(?:\\S+ +){0,' + numContextWords + '}\\S*\\b(?:' +
                        item.matches.map( function(match){return match.replace(/\W/g, '\\$&')} ).join('|') +
                        ')\\b\\S*(?: +\\S+){0,' + numContextWords + '}';
                    context = page.content.match(new RegExp(contextPattern, 'i'));
                }
                var divsuggestion = document.createElement('a');
                divsuggestion.className = 'autocomplete-suggestion';
                divsuggestion.setAttribute('data-term', value);
                divsuggestion.setAttribute('data-title', page.title);
                divsuggestion.setAttribute('href', window.relearn.relBaseUri + page.uri);
                divsuggestion.setAttribute('data-context', context);
                var divtitle = document.createElement('div');
                divtitle.className = 'title';
                divtitle.innerText = '» ' + page.title;
                divsuggestion.appendChild( divtitle );
                var divbreadcrumb = document.createElement('div');
                divbreadcrumb.className = 'breadcrumbs';
                divbreadcrumb.innerText = (page.breadcrumb || '');
                divsuggestion.appendChild( divbreadcrumb );
                if( context ){
                    var divcontext = document.createElement('div');
                    divcontext.className = 'context';
                    divcontext.innerText = (context || '');
                    divsuggestion.appendChild( divcontext );
                }
                results.appendChild( divsuggestion );
            });
            window.relearn.markSearch();
        }
        else if( value.length ) {
            hint.innerText = resolvePlaceholders( window.T_No_results_found, [ value ] );
        }
        input.focus();
        setTimeout( adjustContentWidth, 0 );

        // if we are initiating search because of a browser history
        // operation, we have to restore the scrolling postion the
        // user previously has used; if this search isn't initiated
        // by a browser history operation, it simply does nothing
        var state = window.history.state || {};
        state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
        if( state.hasOwnProperty( 'contentScrollTop' ) ){
            window.setTimeout( function(){
                elc.scrollTop = +state.contentScrollTop;
            }, 10 );
            return;
        }
    })();
}

function initSearchAfterLoad(){
    var input = document.querySelector('#R-search-by-detail');
    if( input ){
        var state = window.history.state || {};
        state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
        state.search = window.location.toString();
        window.history.replaceState( state, '', window.location );
    }

    new autoComplete({
        /* selector for the search box element */
        selectorToInsert: 'search:has(.searchbox)',
        selector: '#R-search-by',
        /* source is the callback to perform the search */
        source: async function( term, response ) {
            let a = await search( term )
            response( a );
        },
        /* renderItem displays individual search results */
        renderItem: function( item, term ) {
            var page = item.page;
            var context = [];
            if( item.matches ){
                var numContextWords = 2;
                var contextPattern = '(?:\\S+ +){0,' + numContextWords + '}\\S*\\b(?:' +
                    item.matches.map( function(match){return match.replace(/\W/g, '\\$&')} ).join('|') +
                    ')\\b\\S*(?: +\\S+){0,' + numContextWords + '}';
                context = page.content.match(new RegExp(contextPattern, 'i'));
            }
            var divsuggestion = document.createElement('div');
            divsuggestion.className = 'autocomplete-suggestion';
            divsuggestion.setAttribute('data-term', term);
            divsuggestion.setAttribute('data-title', page.title);
            divsuggestion.setAttribute('data-uri', window.relearn.relBaseUri + page.uri);
            divsuggestion.setAttribute('data-context', context);
            var divtitle = document.createElement('div');
            divtitle.className = 'title';
            divtitle.innerText = '» ' + page.title;
            divsuggestion.appendChild( divtitle );
            if( context ){
                var divcontext = document.createElement('div');
                divcontext.className = 'context';
                divcontext.innerText = (context || '');
                divsuggestion.appendChild( divcontext );
            }
            return divsuggestion.outerHTML;
        },
        /* onSelect callback fires when a search suggestion is chosen */
        onSelect: function(e, term, item) {
            location.href = item.getAttribute('data-uri');
            e.preventDefault();
        }
    });
};

function initSearch(){
    init();

    window.addEventListener( 'popstate', executeHistorySearch );

    var input = document.querySelector('#R-search-by-detail');
    if( input ){
        input.addEventListener( 'keydown', function(event) {
            // if we are pressing ESC in the searchdetail our focus will
            // be stolen by the other event handlers, so we have to refocus
            // here after a short while
            if (event.key == "Escape") {
                setTimeout( function(){ input.focus(); }, 0 );
            }
        });
    }
    ready( initSearchAfterLoad );
}

initSearch();
})();