(function($){
    // Suppose input name="zip" and name="city" are in form
    // A div with class="geo_suggestions" has to be available too
    $.fn.addSearchAutocomplete = function () {


        var elt = this,
            prev_key_evt_datetime = null,
            prev_search_datetime = null,
            prev_answer_datetime = null,
            suggest_list = document.querySelector('.geo_suggestions');

         const get_element_geom = function(el) {
            var rect = el.getBoundingClientRect(),
            scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
            scrollTop = window.pageYOffset || document.documentElement.scrollTop;
            return { top: rect.top + scrollTop, left: rect.left + scrollLeft, height: el.offsetHeight, width: el.offsetWidth}
        }


        const clear_suggestion_list = function() {
            if (suggest_list) suggest_list.innerHTML = '';
        }

        const fill_with_suggestion = function(item) {
            $('[name="address"]').val(item.getAttribute('data-street'));
            $('[name="zip"]').val(item.getAttribute('data-zip'));
            $('[name="city"]').val(item.getAttribute('data-city'));
            suggest_list.style.display = 'none';
        }

        const display_results = function(features) {
            let geom =  get_element_geom(elt.get(0)),
                list = document.createElement("ul");
            suggest_list.style.position = 'absolute';
            suggest_list.style.display = 'block';
            suggest_list.style.top = (geom.top + geom.height + 2) + 'px';
            suggest_list.style.left = geom.left + 'px';
            suggest_list.style.width = geom.width + 'px';

            features.forEach(function(f){
                let item = document.createElement("li"),
                    cat = street = '';
                if (f.properties.type == 'municipality') {
                    cat = 'fa fa-building';
                } else if (f.properties.type == 'street') {
                    cat = 'fa fa-road';
                } else {
                    cat = 'fa fa-map-marker';
                }
                item.classList.add('geo-suggestion')
                item.setAttribute('data-zip', f.properties.postcode);
                item.setAttribute('data-city', f.properties.city);
                if (f.properties.type == 'housenumber' || f.properties.type == "street") {
                    street = f.properties.name;
                }
                item.setAttribute('data-street',street);
                item.innerHTML = '<i class="' + cat + '"></i>' + f.properties.label
                list.appendChild(item)
            });
            suggest_list.innerHTML = list.outerHTML;
        }

        //fa fa-building fa fa-road fa fa-map-marker
        const search_address = function(q) {
            var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
              if (this.readyState == 4 && this.status == 200) {
                try {
                    const results = JSON.parse(this.responseText)
                    prev_answer_datetime = (new Date()).getTime();
                    if (results.features.length > 0) {
                        display_results(results.features)
                    }
                } catch (err) {
                    console.log(err)
                }

               }
             };

            xhttp.open("GET", "https://api-adresse.data.gouv.fr/search/?q=" + q);
            xhttp.send();

        }
        const launch_search_if_needed = function(text, now) {
            // launch search, excepted if one has been launched few time ago
            if (text.length > 0 && (prev_search_datetime == null || (now - prev_search_datetime >= 500))) {
                prev_search_datetime = now;
                clear_suggestion_list();
                search_address(text);

            }
        }
        elt.on('keyup touchend', function(){
            suggest_list.style.display = 'none';
            var text = elt.val().trim(),
                now = (new Date()).getTime();
            if (prev_key_evt_datetime == null) {
                prev_key_evt_datetime = now;
            } else {
                if ((now - prev_key_evt_datetime) > 750 && text.length > 0) {
                    // elapsed time is enough to consider it as a possible end
                    launch_search_if_needed(text, now);
                }
            }
            prev_key_evt_datetime = now
            setTimeout(function(){
                // needed to launch search if no more keyup
                let now = (new Date()).getTime();
                launch_search_if_needed(elt.val().trim(), now);
            }, 500);
        });

        document.addEventListener('click', function (event) {
            if (event.target.tagName == "LI" && event.target.matches('.geo-suggestion')) {
                fill_with_suggestion(event.target);
            } else {
                suggest_list.style.display = 'none';
            }
        });

    };
}(jQuery));
