/* 
    Created on : Aug 31, 2015
    Author     : yeozkaya@gmail.com
*/
;
(function ($) {

    var options = {
        geojsonServiceAddress: "http://yourGeoJsonSearchAddress",
        placeholderMessage: "Search...",
        foundRecordsMessage: "showing results.",
        limit: 10,
        notFoundMessage: "not found.",
        notFoundHint: "Make sure your search criteria is correct and try again.",
        drawColor: "blue",
        pointGeometryZoomLevel: -1, //Set zoom level for point geometries -1 means use leaflet default.
        pagingActive: true,
        map_obj: null,
        serachboxID:null

    };

    var activeResult = -1;
    var resultCount = 0;
    var lastSearch = "";
    var searchLayer;
    var focusLayer;
    var searchLayerType; // 0 --> One geometry, 1--> Multiple
    var features = [];
    var featureCollection = [];
    var offset = 0;
    var collapseOnBlur = true;
    var searchID = null;
    var targetedElement = null;

    $.fn.GeoJsonAutocomplete = function (userDefinedOptions) {
        var keys = Object.keys(userDefinedOptions);
        for (var i = 0; i < keys.length; i++) {
            options[keys[i]] = userDefinedOptions[keys[i]];
        }

        map = options.map_obj.map;

         searchID = options.serachboxID;
        $(this).each(function () {
            var element = $(this);
            this.targetedElement = element;
            $(this.targetedElement).parent().addClass("searchContainer");
            $(this.targetedElement).parent().addClass("wpgmp-autocomplete-wrapper");
            $(this)[0].value = "";
            $(this).delayKeyup(function (event) {
                var target = $(event.target);
                console.log("Event Code");
                console.log(event.keyCode)
                console.log($(target).attr('name'));
                switch (event.keyCode) {
                    case 13: // enter
                        searchButtonClick(target);
                        break;
                    case 38: // up arrow
                        prevResult(target);
                        break;
                    case 40: // down arrow
                        nextResult(target);
                        break;
                    case 37: //left arrow, Do Nothing
                    case 39: //right arrow, Do Nothing
                        break;
                    default:

                        if ($(target)[0].value.length > 0) {
                            offset = 0;
                            getValuesAsGeoJson(false,target);
                        }
                        else {
                            clearButtonClick(target);
                        }
                        break;
                }
            }, 300);

            $(this.targetedElement).focus(function () {
                var resultsElements = getResultsDiv(this);

                if ($(resultsElements).length > 0) {
                    //$(resultsElements)[0].style.visibility = "visible";
                    $(resultsElements).find('.wpgmp-autosuggest-results').show();
                }
            });

            $(this.targetedElement).blur(function (event) {
                var resultsElements = getResultsDiv(this);
                if ($(resultsElements).length > 0) {
                    if (collapseOnBlur) {
                        //$(resultsElements)[0].style.visibility = "collapse";
                        $(resultsElements).find('.wpgmp-autosuggest-results').hide();
                    }
                    else {
                        collapseOnBlur = true;

                        window.setTimeout(function ()
                        {
                            $(event.target).focus();
                        }, 0);
                    }
                }

            });

        });
    };

    $.fn.delayKeyup = function (callback, ms) {
        var timer = 0;
        $(this).keyup(function (event) {

            if (event.keyCode !== 13 && event.keyCode !== 38 && event.keyCode !== 40) {
                clearTimeout(timer);
                timer = setTimeout(function () {
                    callback(event);
                }, ms);
            }
            else {
                callback(event);
            }
        });
        return $(this);
    };

    function getValuesAsGeoJson(withPaging,target) {
        console.log("Geo Json is called");
        activeResult = -1;
        features = [];
        featureCollection = [];
        var limitToSend = options.limit;
        if (withPaging) {
            limitToSend++;
        }
        lastSearch = target[0].value;

        if (lastSearch === "") {
            return;
        }

        var data = {
            q: lastSearch,
            limit: limitToSend,
            format: 'json',
            addressdetails: true    
        };

        if(options.pagingActive){
            data.offset = offset;
        }
        
        $.ajax({
            url: options.geojsonServiceAddress,
            type: 'GET',
            data: data,
            dataType: 'json',
            success: function (json) {
            resultCount = json.length;
            features = json;

            if (limitToSend === resultCount)
                featureCollection = json.slice(0, json.length - 1);
            else
                featureCollection = json;
                
                createDropDown(withPaging,target);
                searchLayerType = (withPaging ? 1 : 0);
            },
            error: function () {
                processNoRecordsFoundOrError(target);
            }
        });

    }

    function getResultsDiv(target){
        var parent = $(target).parent();
        return $(parent).find('.resultsDiv');
    }
    function createDropDown(withPaging,target) {

        console.log("create dropdown is called");
        var parent = target.parent();

        $(parent).find('.resultsDiv').remove();
        
        parent.append("<div class='result resultsDiv'><ul class='list  resultList wpgmp-autosuggest-results'></ul><div>");

        var resultsElements = getResultsDiv(target);
        $(resultsElements)[0].style.position = target[0].style.position;
        $(resultsElements)[0].style.left = (parseInt(target[0].style.left) - 10) + "px";
        $(resultsElements)[0].style.bottom = target[0].style.bottom;
        $(resultsElements)[0].style.right = target[0].style.right;
        $(resultsElements)[0].style.top = (parseInt(target[0].style.top) + 25) + "px";
        $(resultsElements)[0].style.zIndex = target[0].style.zIndex;

        var loopCount = features.length;
        var hasMorePages = false;
        if (withPaging && features.length === options.limit + 1) { //Has more pages
            loopCount--;
            hasMorePages = true;
            resultCount--;
        }

        for (var i = 0; i < loopCount; i++) {

            var html = "<li  data-index='listElement"+i+"' class='listResult listElement"+i+"'>";
            html += "<span data-index='listElementContent"+i+"' class='content listElementContent"+i+"'>";
            html += "<font size='2' color='#333' class='title'>" + features[i].display_name + "</font><font size='1' color='#8c8c8c'> " + features[i].lat + " -- " + features[i].lon + "<font></span></li>";

            //$("#resultList").append(html);
            $(resultsElements).find(".resultList").append(html);
            $(resultsElements).find(".listElement" + i).mouseenter(function () {
                listElementMouseEnter(this,target);
            });

            $(resultsElements).find(".listElement" + i).mouseleave(function () {
                listElementMouseLeave(this,target);
            });

            $(resultsElements).find(".listElement" + i).mousedown(function () {
                listElementMouseDown(this,target);
            });
        }

        if (withPaging) {
            var prevPic = "prev.png";
            var nextPic = "next.png";
            var prevDisabled = "";
            var nextDisabled = "";

            if (offset === 0) {
                prevPic = "prev_dis.png";
                prevDisabled = "disabled";
            }

            if (!hasMorePages) {
                nextPic = "next_dis.png";
                nextDisabled = "disabled";
            }
            var image_url = options.map_obj.settings.images_url;
            var htmlPaging = "<div align='right' class='pagingDiv'>" + (offset + 1) + " - " + (offset + loopCount) + " " + options.foundRecordsMessage + " ";
            htmlPaging += "<input id='pagingPrev1' type='image' src='"+image_url + prevPic + "' width='16' height='16' class='pagingPrev pagingArrow' " + prevDisabled + ">";
            htmlPaging += "<input id='pagingNext1' type='image' src='"+image_url + nextPic + "' width='16' height='16' class='pagingNext pagingArrow' " + nextDisabled + "></div>";
            $(resultsElements).append(htmlPaging);

            $(resultsElements).find(".pagingPrev").mousedown(function () {
                prevPaging(target);
            });

            $(resultsElements).find(".pagingNext").mousedown(function () {
                nextPaging(target);
            });

            drawGeoJsonList(target);
        }
    }

    function listElementMouseEnter(listElement,target) {

        var resultsElements = getResultsDiv(target);
        var indexAttr = listElement.getAttribute('data-index');
        var index = parseInt(indexAttr.substr(11));
        if (index !== activeResult) {
            $(resultsElements).find('.listElement' + index).toggleClass('mouseover');
        }
    }

    function listElementMouseLeave(listElement,target) {
        var resultsElements = getResultsDiv(target);
        var indexAttr = listElement.getAttribute('data-index');
        var index = parseInt(indexAttr.substr(11));

        if (index !== activeResult) {
            $(resultsElements).find('.listElement' + index).removeClass('mouseover');
        }
    }

    function listElementMouseDown(listElement,target) {
        var resultsElements = getResultsDiv(target);
        var indexAttr = listElement.getAttribute('data-index');
        var index = parseInt(indexAttr.substr(11));

        if (index !== activeResult) {
            if (activeResult !== -1) {
                $(resultsElements).find('.listElement' + activeResult).removeClass('active');
            }

            $(resultsElements).find('.listElement' + index).removeClass('mouseover');
            $(resultsElements).find('.listElement' + index).addClass('active');

            activeResult = index;
            fillSearchBox(target);

            if (searchLayerType === 0) {
                drawGeoJson(activeResult,target);
            }
            else {
                focusGeoJson(activeResult,target);
            }
        }
    }


    function drawGeoJsonList(target) {
        if (searchLayer !== undefined) {
            map.removeLayer(searchLayer);
            searchLayer = undefined;
        }

        searchLayer = L.geoJson(featureCollection, {
            style: function (feature) {
                return {color: "#D0473B"};
            },
            pointToLayer: function (feature, latlng) {
                return new L.CircleMarker(latlng, {radius: 5, fillOpacity: 0.85});
            },
            onEachFeature: function (feature, layer) {
                layer.bindPopup(feature.properties.popupContent);
            }
        });

        map.addLayer(searchLayer);

    }

    function focusGeoJson(index,target) {

        drawGeoJsonOnFocusLayer(index,target);
    }

    function drawGeoJson(index,target) {

        if (searchLayer !== undefined) {
            searchLayer = undefined;
        }

        if (index === -1)
            return;

        var drawStyle = {
            color: options.drawColor,
            weight: 5,
            opacity: 0.65,
            fill: false
        };

        searchLayer = L.geoJson(features[index].geometry, {
            style: drawStyle,
            onEachFeature: function (feature, layer) {
                layer.bindPopup(features[index].properties.popupContent);
            }
        });

        var center = new L.LatLng(features[index].lat, features[index].lon);

       if(!($(target).hasClass('wpgmp_search_input'))){
           
            var marker = new L.Marker(center,{
                icon: L.icon({ 
                    iconUrl: options.map_obj.settings.marker_default_icon,
                     iconAnchor: [15, 55], 
                     popupAnchor: [0, -55],

                 }),
            });
            marker.addTo(map);
            var content = features[index].display_name;
            marker.bindPopup('<div class="wpgmp_infowindow"><div class="wpgmp_iw_content">'+content+'</div></div>');
           
       }

        if($(target).hasClass('wpgmp_search_input')){
            if( typeof options.map_obj.map_data.listing !='undefined' && typeof options.map_obj.map_data.listing.display_radius_filter !='undefined' && options.map_obj.map_data.listing.display_radius_filter === true ) {
                options.map_obj.search_area = center;
            }
            options.map_obj.update_filters();
        }
        map.panTo(center);

    }

    function drawGeoJsonOnFocusLayer(index,target) {

        if (focusLayer !== undefined) {
            map.removeLayer(focusLayer);
            focusLayer = undefined;
        }

        if (index === -1)
            return;

        var drawStyle = {
            color: options.color,
            weight: 5,
            opacity: 0.65,
            fill: false
        };

        focusLayer = L.geoJson(features[index].geometry, {
            style: drawStyle,
            onEachFeature: function (feature, layer) {
                layer.bindPopup(features[index].properties.popupContent);
            }
        });

        map.addLayer(focusLayer);

    }

    function fillSearchBox(target) {
        try {
          const feature = features[activeResult];
          const locationForm = target.closest("form");
      
          if (!feature || !locationForm.length) return;
      
          const displayName = feature.display_name || lastSearch;
          const lat = parseFloat(feature.lat);
          const lng = parseFloat(feature.lon);
          const address = feature.address || {};
      
          const city = address.city || address.county || "";
          const state = address.state || "";
          const country = address.country || "";
          const postal = address.postcode || "";
      
          const inputName = target.attr("name");
      
          // Common function to create marker and center map
          const placeMarker = () => {
            const markerLatLng = L.latLng(lat, lng);
      
            if (map_obj.searchMarker) {
              map_obj.map.removeLayer(map_obj.searchMarker);
            }
      
            map_obj.searchMarker = L.marker(markerLatLng, {
              icon: L.icon({
                iconUrl: map_obj.settings.marker_default_icon || "",
                iconSize: [30, 40],
                iconAnchor: [15, 40],
              }),
              draggable: true,
            }).addTo(map_obj.map);
      
            map_obj.map.setView(markerLatLng, 17);
      
            if (typeof map_obj.marker_bind === "function") {
              map_obj.marker_bind(map_obj.searchMarker);
            }
          };
      
          // Case: location_address (backend form)
          if (inputName === "location_address") {
            $(target).val(displayName);
            locationForm.find(".google_latitude").val(lat);
            locationForm.find(".google_longitude").val(lng);
            locationForm.find(".google_city").val(city);
            locationForm.find(".google_state").val(state);
            locationForm.find(".google_country").val(country);
            locationForm.find(".google_postal_code").val(postal);
      
            placeMarker();
          } // Case: wpgmp_metabox_location (backend form)
          else if (inputName === "wpgmp_metabox_location") {
            $("input[name='wpgmp_metabox_latitude']").val(lat);
            $("input[name='wpgmp_metabox_longitude']").val(lng);
            $("input[name='wpgmp_metabox_location_city']").val(city);
            $("input[name='wpgmp_metabox_location_state']").val(state);
            $("input[name='wpgmp_metabox_location_country']").val(country);
            $("input[name='wpgmp_metabox_location_hidden']").val(displayName);
      
            placeMarker();
          } // Case: map-search-control (frontend)
          else if (inputName === "map-search-control") {
            const markerLatLng = L.latLng(lat, lng);
      
            if (map_obj.searchMarker) {
              map_obj.map.removeLayer(map_obj.searchMarker);
            }
      
            map_obj.searchMarker = L.marker(markerLatLng, {
              icon: L.icon({
                iconUrl: map_obj.settings.marker_default_icon || "",
                iconSize: [30, 40],
                iconAnchor: [15, 40],
              }),
              draggable: false,
            }).addTo(map_obj.map);
      
            const zoomLevel = parseInt(map_obj.settings.zoom_level_after_search || 10);
            map_obj.map.setView(markerLatLng, zoomLevel);
      
            if (typeof map_obj.marker_bind === "function") {
              map_obj.marker_bind(map_obj.searchMarker);
            }
          } // Default / Filter Input
          else {
            if (typeof map_obj !== "undefined" && map_obj.map) {
              const markerLatLng = L.latLng(lat, lng);
              map_obj.map.setView(markerLatLng, 16);
      
              target.data("latitude", lat);
              target.data("longitude", lng);
      
              if (
                inputName === "wpgmp_search_input" ||
                target.data("wpgmp-filter-by") === "search"
              ) {
                map_obj.search_area = markerLatLng;
      
                if (typeof map_obj.update_filters === "function") {
                  map_obj.update_filters();
                }
      
                if (typeof map_obj.display_circle_when_searched === "function") {
                  map_obj.display_circle_when_searched(feature, target);
                }
              }
            }
          }
      
          // Final: Set the input field to displayName
          target.val(displayName);
        } catch (e) {
          console.warn("Leaflet AutoSuggest Error:", e);
        }
      }
      

    function nextResult(target) {
        var resultsElements = getResultsDiv(target);
        if (resultCount > 0) {
            if (activeResult !== -1) {
                $(resultsElements).find('.listElement' + activeResult).toggleClass('active');
            }

            if (activeResult < resultCount - 1) {
                $(resultsElements).find('.listElement' + (activeResult + 1)).toggleClass('active');
                activeResult++;
            }
            else {
                activeResult = -1;
            }

            fillSearchBox(target);

            if (activeResult !== -1) {
                if (searchLayerType === 0) {
                    drawGeoJson(activeResult,target);
                }
                else {
                    focusGeoJson(activeResult,target);
                }
            }

        }
    }

    function prevResult(target) {
        var resultsElements = getResultsDiv(target);
        if (resultCount > 0) {
            if (activeResult !== -1) {
                $(resultsElements).find('.listElement' + activeResult).toggleClass('active');
            }

            if (activeResult === -1) {
                $(resultsElements).find('.listElement' + (resultCount - 1)).toggleClass('active');
                activeResult = resultCount - 1;
            }
            else if (activeResult === 0) {
                activeResult--;
            }
            else {
                $(resultsElements).find('.listElement' + (activeResult - 1)).toggleClass('active');
                activeResult--;
            }

            fillSearchBox(target);

            if (activeResult !== -1) {
                if (searchLayerType === 0) {
                    drawGeoJson(activeResult,target);
                }
                else {
                    focusGeoJson(activeResult,target);
                }
            }
        }
    }

    function clearButtonClick(target) {
        target[0].value = "";
        lastSearch = "";
        resultCount = 0;
        features = [];
        activeResult = -1;
        var resultsElements = getResultsDiv(target);
        $(resultsElements).remove();
        if (searchLayer !== undefined) {
            map.removeLayer(searchLayer);
            searchLayer = undefined;
        }
        if (focusLayer !== undefined) {
            map.removeLayer(focusLayer);
            focusLayer = undefined;
        }
    }

    function searchButtonClick(target) {
        getValuesAsGeoJson(options.pagingActive,target);

    }

    function processNoRecordsFoundOrError(target) {
        resultCount = 0;
        features = [];
        activeResult = -1;
        var resultsElements = getResultsDiv(target);
        $(resultsElements).remove();
        if (searchLayer !== undefined) {
            map.removeLayer(searchLayer);
            searchLayer = undefined;
        }

        var parent = target.parent();
        resultsElements = getResultsDiv(target);
        $(resultsElements).remove();
        parent.append("<div class='result resultsDiv'><i>" + lastSearch + " " + options.notFoundMessage + " <p><small>" + options.notFoundHint + "</small></i><div>");
    }

    function prevPaging(target) {
        target[0].value = lastSearch;
        offset = offset - options.limit;
        getValuesAsGeoJson(true,target);
        collapseOnBlur = false;
        activeResult = -1;
    }

    function nextPaging(target) {
        target[0].value = lastSearch;
        offset = offset + options.limit;
        getValuesAsGeoJson(true,target);
        collapseOnBlur = false;
        activeResult = -1;
    }
})(jQuery);
