﻿/// <reference path="../API/Agility.UGC.API.js" />

Edentity.RegisterNamespace("Shoppers.Controls.StoreLocator");

(function(SLP, $) {

    var opts = {
        StoreHours: "",
        MapId: 'map',
        IconPath: '',
        ResultsListID: 'div.List',
        SelectButtonImageURL: "",
        CloseButtonImageURL: "",
        DetailsLabel: "",
        StoreLocatorAreaID: "",
        PageNo: 0,
        NumClosest: 100,
        StoreDetailsLinkLabel: "",
        ShowResults: false,
        StoreFields: "",
        CosmeticsSelection: "",
        FragranceSelection: "",
        SkincareSelection: "",
        Province: "",
        SearchResultsGroup1Width: "",
        SearchResultsGroup2Width: "",
        SearchResultsGroup3Width: "",
        SearchResultsGroup4Width: "",
        SearchResultsGroup1: "",
        SearchResultsGroup2: "",
        SearchResultsGroup3: "",
        SearchResultsGroup4: ""
    };

    var StoreLocatorArea = null;
    var map = null;
    var geocoder;
    var resultsList = null;
    var MapCenter = null;
    var ddlResultsPerPage = 3;

    SLP.OnInit = function(p) {

        opts = $.extend({}, opts, p || {});

        InitControls();

        if (opts.ShowResults) {
            if ($storeNum && $storeNum.val()) {
				var num = parseInt($storeNum.val());
				if (!isNaN(num)) {
					Shoppers.Controls.StoreLocator.SearchByStoreNum(num);
				}
            } else {
                Shoppers.Controls.StoreLocator.Search(buildAddressString(true));
            }
        }

        GenerateDetailsColumnHtml(opts.SearchResultsGroup1, opts.SearchResultsGroup1Width);
    };

    function GenerateDetailsColumnHtml(groupReferenceName, width) {

        var html = "";

        $.ajax({
            type: 'POST',
            url: Edentity.ResolveUrl('~/WebServices/AjaxService.asmx/GetDetailGroup'),
            data: "{'groupRef':'" + groupReferenceName + "'}",
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function(res) {

                html += "<b>" + res.d.Key + "</b><br/>";
                //TODO: Call from store context, and find a way to get property name = res.d.Value(i) from store. Maybe: store["'" + res.d.Value(i) + "'"] ??
                //html += store.Associate + "<br/><br/>";
            }
        });
    }

    SLP.Search = function(address) {
        $.ajax({
            type: 'POST',
            url: Edentity.ResolveUrl('~/WebServices/AjaxService.asmx/SearchByAddress'),
            data: "{'Address':'" + address + "'}",
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function(res) {

                //Show the results div
                var divs = $("> div", StoreLocatorArea);
                divs.eq(0).hide();
                divs.eq(1).show();

                $.scrollTo(divs.eq(1), 800);

                if (res != null && res.d != null) {

                    //Inits Google maps API
                    InitGObjects();

                    MapCenter = res.d;
                    map.checkResize();
                    map.setCenter(new GLatLng(res.d.Latitude, res.d.Longitude), 10);

                    //Search for the stores
                    GetNearestStores();
                    $("h1 span", resultsList.parent().parent().parent()).html("&nbsp;" + buildAddressString());
                }
                else {
                    addressNotFound();
                }
            },
            complete: function(XMLHttpRequest, textStatus) {
                //alert(XMLHttpRequest.status + ' ' + textStatus);
                //alert(XMLHttpRequest.responseText);
            }
        });
    };

    SLP.SearchByStoreNum = function(storeNum) {
        $.ajax({
            type: 'POST',
            url: Edentity.ResolveUrl('~/WebServices/AjaxService.asmx/SearchByStoreNum'),
            data: "{'StoreNum':" + storeNum + "}",
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function(res) {
                //Show the results div
                var divs = $("> div", StoreLocatorArea);
                divs.eq(0).hide();
                divs.eq(1).show();

                $.scrollTo(divs.eq(1), 800);

                if (res != null && res.d != null) {

                    //Inits Google maps API
                    InitGObjects();

                    MapCenter = res.d;
                    map.setCenter(new GLatLng(res.d.Latitude, res.d.Longitude), 10);

                    //Search for the stores
                    ShowStores([res.d]);
                }
                else {
                    addressNotFound();
                }
            }
        });
    };

    SLP.OnReset = function(resetValues) {
        //Show the search div
        var divs = $("> div", StoreLocatorArea);

        resultsList.html("");
        if (map != null) {
            map.clearOverlays();
        }

        divs.eq(1).hide();
        divs.eq(0).show();

        if (resetValues) {

            $("#aspnetForm")[0].reset();
            $("input[id$=txtPostalCode]", StoreLocatorArea).val("");
        }

        $("div.SearchResults div.List").hide();
        $("#divNoStoresFoundMessage").hide();

        opts.PageNo = 0;
    };


    function clearForm(form) {
        // iterate over all of the inputs for the form
        // element that was passed in
        $(':input', form).each(function() {
            var type = this.type;
            var tag = this.tagName.toLowerCase(); // normalize case
            // it's ok to reset the value attr of text inputs,
            // password inputs, and textareas
            if (type == 'text' || type == 'password' || tag == 'textarea')
                this.value = "";
            // checkboxes and radios need to have their checked state cleared
            // but should *not* have their 'value' changed
            else if (type == 'checkbox' || type == 'radio')
                this.checked = false;
            // select elements need to have their 'selectedIndex' property set to -1
            // (this works for both single and multiple select elements)
            else if (tag == 'select')
                this.selectedIndex = -1;
        });
    };

    function InitControls() {
        StoreLocatorArea = $(opts.StoreLocatorAreaID);
        resultsList = $(opts.ResultsListID);

        ddlResultsPerPage = $("select[id$=ddlResultsPerPage]").val();
        $storeNum = $("input[id$=txtStoreNumber]");

        $("a.SearchButton", StoreLocatorArea).each(function() {
            $(this).click(function() {
                ddlResultsPerPage = $("select[id$=ddlResultsPerPage]").val();
                $storeNum = $("[id$=txtStoreNumber]", StoreLocatorArea);
                if ($storeNum && $storeNum.val()) {
					var num = parseInt($storeNum.val());
					if (!isNaN(num)) {
						Shoppers.Controls.StoreLocator.SearchByStoreNum(num);
					}
                } else {
                    Shoppers.Controls.StoreLocator.Search(buildAddressString(true));
                }
            });
        });
        $("a.ResetButton", StoreLocatorArea).click(function() {
            Shoppers.Controls.StoreLocator.OnReset(true);
        });
//        $("a.StartNewSearchButton", StoreLocatorArea).click(function() {
//            Shoppers.Controls.StoreLocator.OnReset(false);
//        });

        switch (opts.StoreHours) {
            case "24":
                $("input[name=StoreHours]:eq(1)", StoreLocatorArea).click();
                break;
            case "12":
                $("input[name=StoreHours]:eq(2)", StoreLocatorArea).click();
                break;
        }

        populateStoreFields();

        $("input[id$=txtPostalCode]", StoreLocatorArea).focus();

        //attach click events for advanced search toggle
        $(".divAdvancedSearchToggleHide span").click(function() {
            $(".divAdvancedSearchToggleHide").hide();
            $(".divAdvancedSearchToggleShow").show();
            $("#AdvancedSearchFields").slideToggle();
        });

        $(".divAdvancedSearchToggleShow span").click(function() {
            $(".divAdvancedSearchToggleHide").show();
            $(".divAdvancedSearchToggleShow").hide();
            $("#AdvancedSearchFields").slideToggle();
        });

        $("select#ddlStoreTypes").change(function() {
            ToggleAdvancedSearch();
        });

        ToggleAdvancedSearch();
    };

    function ToggleAdvancedSearch() {
        if (typeof $("select#ddlStoreTypes option:selected").attr("advanced") != "undefined") {
            var queryStrings = window.location.search.substring(1).split("&");
            var queryStringVariables = ",";
            for (var index in queryStrings) {
                queryStringVariables += queryStrings[index].split("=")[0] + ",";
            }

            if (queryStringVariables.indexOf(",sf,") > 0 ||
                    queryStringVariables.indexOf(",cs,") > 0 ||
                        queryStringVariables.indexOf(",fs,") > 0 ||
                            queryStringVariables.indexOf(",ss,") > 0 ||
                                queryStringVariables.indexOf(",sh,") > 0) {

                $(".divAdvancedSearchToggleShow").hide();
                $(".divAdvancedSearchToggleHide").show();
                $("#AdvancedSearchFields").show();

            }
            else {
                $(".divAdvancedSearchToggleShow").show();
                $(".divAdvancedSearchToggleHide").hide();
                $("#AdvancedSearchFields").hide();
            }
        }
        else {
            $(".divAdvancedSearchToggleHide").hide();
            $(".divAdvancedSearchToggleShow").hide();
            $("#AdvancedSearchFields").hide();
        }
    }

    function populateStoreFields() {

        //address fields are populated in codebehind, except for province (client side)
        $("#selectProvinces").find("option[value='" + opts.Province + "']").attr("selected", true);

        //ALL CHECKBOXES IN "AdvancedSearchField" div
        //fields are passed in the query string "sf", and are to be comma separated
        var $checkboxStoreFields = opts.StoreFields.split(',');
        $("#AdvancedSearchFields input[type=checkbox]").each(function() {
            //add lowercase version of field attribute for following selector to work (and be case insensitive) - this is optional
            $(this).attr("fieldLC", $(this).attr("field").toLowerCase());
        });

        for (var index in $checkboxStoreFields) {
            $("#AdvancedSearchFields input[type=checkbox][fieldLC='" + $.trim($checkboxStoreFields[index].toLowerCase()) + "']").attr("checked", true);
        }

        //COSMETICS, FRAGRANCE, SKINCARE
        //<select> elements with field = Cosmetics1, Cosmetics2, and Cosmetics3, respectively
        //query strings are passed in as cs, fs, ss parameters and selected values are comma separated

        performMultiSelect("Cosmetics1", opts.CosmeticsSelection);
        performMultiSelect("Cosmetics2", opts.FragranceSelection);
        performMultiSelect("Cosmetics3", opts.SkincareSelection);
    }


    //selects values from "valueCSV" in selectField: "selectFieldName"
    function performMultiSelect(selectFieldName, valueCSV) {

        var $valueArray = valueCSV.split(',');

        $("#divBeautySelection select option").each(function() {
            //add lowercase version of field attribute for following selector to work (and be case insensitive) - this is optional
            $(this).attr("valLC", $(this).val().toLowerCase());
        });

        for (var index in $valueArray) {
            $("#divBeautySelection select[field='" + selectFieldName + "']").find("option[valLC='" + $.trim($valueArray[index].toLowerCase()) + "']").attr("selected", true);
        }
    }

    function buildAddressString(appendCanada) {
        var criteria = [],
            $container = $(opts.StoreLocatorAreaID),
            inputs = ["txtAddress", "txtCity", "selectProvinces", "txtPostalCode"];

        $.each(inputs, function(idx, id) {
            var $input = $("[id$=" + id + "]", $container);
            if ($input && $input.val()) {
                if ($input.is("select")) {
                	criteria.push($("option:selected", $input).text());
                } else {
					criteria.push($input.val());
                }
            }
        });
        if (appendCanada === true) {
            criteria.push("Canada");
        }
        return criteria.join(", ");
    }

    function InitGObjects() {
        if (map == null && GBrowserIsCompatible()) {
            map = new GMap2(document.getElementById(opts.MapId));
            map.setUIToDefault();
            geocoder = new GClientGeocoder();
        }
    };

    function AddFilterForControl(currentFilter, control) {
        var value = $.trim(control.val());

        if (!value) return currentFilter;

        if (currentFilter.length > 0) {
            currentFilter += ";";
        }
        return currentFilter + control.attr("field") + "=" + value;
    }

    function AdvancedFieldFilters() {
        var sqlSearch = AddFilterForControl("", $("input[name=StoreHours]:checked", StoreLocatorArea));
        $("#divStoreServices1 input:checked").each(function() {
            sqlSearch = AddFilterForControl(sqlSearch, $(this));
        });
        $("#divSpecialServices input:checked").each(function() {
            sqlSearch = AddFilterForControl(sqlSearch, $(this));
        });
        $("#divStoreServices2 input:checked").each(function() {
            sqlSearch = AddFilterForControl(sqlSearch, $(this));
        });
        $("#divPhotoServices input:checked").each(function() {
            sqlSearch = AddFilterForControl(sqlSearch, $(this));
        });
        if (opts.IsAmigo) {
            if (sqlSearch.length > 0) {
                sqlSearch += ";";
            }
            sqlSearch += "HasAmigo=True";
        }

        return sqlSearch;
    };

    function LargeTextFilterSettings() {
        var sqlSearch = "";

        $("#divBeautySelection select").each(function() {
            ctrl = $(this);
            $('option:selected', ctrl).each(function() {
                v = $.trim($(this).text());
                if (v != "") {
                    if (sqlSearch.length > 0) {
                        sqlSearch += " || ";
                    }
                    sqlSearch += ctrl.attr("field") + " = '" + v + "'";
                }
            });
        });

        return sqlSearch;
    };

    var SearchResults = null;

    function GetNearestStores() {

        if (MapCenter == null) return;

        var latLngBounds = map.getBounds();
        var fLat = parseFloat(MapCenter.Latitude),
        fLng = parseFloat(MapCenter.Longitude),
        xOffset = 0.31,
        yOffset = 0.15;

        var storeType = $("select[id$='ddlStoreTypes'] option:selected").attr("description");

        var params =
            "{'Latitude':" + MapCenter.Latitude + ",'Longitude':" + MapCenter.Longitude +
            ",'MinX':" + (fLng - xOffset) + ",'MinY':" + (fLat - yOffset) +
            ",'MaxX':" + (fLng + xOffset) + ",'MaxY':" + (fLat + yOffset) +
            ",'Closest':" + opts.NumClosest + ",'ResultsPerPage':" + ddlResultsPerPage +
            ",'AdvancedFilters':\"" + AdvancedFieldFilters() + "\"" +
            ",'LargeTextFilters':\"" + LargeTextFilterSettings() + "\"" +
            ",'StoreType':\"" + storeType + "\"" +
            "}";

        $.ajax({
            type: 'POST',
            url: Edentity.ResolveUrl('~/WebServices/AjaxService.asmx/GetPagedNearestStores'),
            data: params,
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function(res) {

                if (res != null && res.d != undefined && res.d != null && res.d.length > 0) {
                    ShowStores(res.d);
                }
                else {
                    storesNotFound();
                }
            },
            complete: function(XMLHttpRequest, textStatus) {
                //alert(XMLHttpRequest.status + ' ' + textStatus);
                //alert(XMLHttpRequest.responseText);
            }
        });
    }

    function addressNotFound() {
        InitGObjects();
        map.setCenter(new GLatLng(56.170023, -106.347656), 4);
        storesNotFound();
    }

    function storesNotFound() {
        $("div.SearchResults div.List").hide();
        $("#pResultsDescriptionLabel, .MapLegend").hide();
        $("#divNoStoresFoundMessage").show();
        map.setZoom(4);
    }

    function ShowStores(stores) {
        $("#divNoStoresFoundMessage").hide();
        $("#pResultsDescriptionLabel, .MapLegend").show();
        $("div.SearchResults div.List").show();

        //Saved for pagination
        SearchResults = stores;

        LoadStores(stores);
        RenderPager(stores.length);
    }

    SLP.RenderView = function(newPage, storesCount) {
        opts.PageNo = newPage;

        //Render markers & rows
        $("td.DetailsRow", resultsList).each(function() {
            var td = $(this);
            td.hide();
            $("a.Details", td.parent().prev()).removeClass("Expanded");
        });

        var trs = $("tr[valign=top]", resultsList);
        var bounds = new GLatLngBounds();
		var numStoresShown = 0;
        for (var i = 0; i < storesCount; i++) {
            if (i >= (opts.PageNo * ddlResultsPerPage) && i < ((opts.PageNo + 1) * ddlResultsPerPage)) {
                mapMarkers[i].show();
                trs.eq(i).show();
                bounds.extend(mapMarkers[i].getPoint());
				numStoresShown++;
            }
            else {
                mapMarkers[i].hide();
                trs.eq(i).hide();
            }
        }

		var zoomLevel = numStoresShown == 1
			? opts.MapZoomLevel
			: map.getBoundsZoomLevel(bounds);
		
		map.setCenter(bounds.getCenter(), zoomLevel);
		
        RenderPager(storesCount);
    };

    function renderPagerOnClick(pageno, pagecount, text) {
        var oc = "";
        if (pageno != opts.PageNo) {
            oc += "<a href='javascript:;' onclick='Shoppers.Controls.StoreLocator.RenderView(" + pageno + "," + pagecount + ")'";
            oc += ">" + text + "</a>";
        }
        else {
            oc += "<span>" + text + "</span>";
        }
        return oc + "&nbsp;&nbsp;";
    };

    function RenderPager(storesCount) {
        var pagers = $("div.SearchResults div.ResultsPager", StoreLocatorArea);
        var pdivs = $("div", pagers.eq(0));

        var s = parseInt(opts.PageNo * ddlResultsPerPage) + parseInt(ddlResultsPerPage);
        if (s > storesCount) {
            s = storesCount;
        }
        var pager = (opts.PageNo * ddlResultsPerPage + 1) + "&nbsp;-&nbsp;" + s + "&nbsp;of&nbsp;" + storesCount;
        pdivs.eq(0).html(pager);

        var pageNav = "";
        var pageCount = Math.ceil(storesCount / ddlResultsPerPage);
        if (pageCount > 1) {
            pageNav += renderPagerOnClick(opts.PageNo > 0 ? opts.PageNo - 1 : 0, storesCount, "prev");
            pageNav += renderPagerOnClick(opts.PageNo < pageCount - 1 ? opts.PageNo + 1 : pageCount - 1, storesCount, "next");
        }
        pdivs.eq(1).html(pageNav);

        pagers.eq(1).html(pagers.eq(0).html());
    };

    function LoadStores(stores) {
        LoadList(stores);
        LoadMarkers(stores);
    };

    function getStoreAttribute(store, attrName) {
        var attr = store[attrName + opts.DetailsLabels.AttributeSuffix];
        if (attr != null && attr != "") {
            return attr + "<br/>";
        }
        return "";
    };

    function LoadList(stores) {

        if (typeof stores == 'undefined' || stores == null || stores.length == 0) return;

        var templateUrl = Agility.ResolveUrl("~/ClientTemplates/StoreLocatorResults.htm");

        resultsList.empty();
        resultsList.setTemplateURL(templateUrl, [], { filter_data: false });
        resultsList.setParam("Phone", "Phone");
        resultsList.setParam("PageSize", ddlResultsPerPage);
        resultsList.setParam("StoreDetailsLinkLabel", opts.StoreDetailsLinkLabel);
        resultsList.processTemplate(stores);

        $("a.Details", resultsList).click(bindStoreDetailsToggle);
    };

    function bindStoreDetailsToggle() {
        var a = $(this);
        var td = $("td", a.parent().parent().parent().next());
        var recordID = a.attr("recordid");

        td.toggle();
        a.toggleClass("Expanded");

        if (!td.is(".Filled")) {
            $.ajax({
                type: 'POST',
                url: Edentity.ResolveUrl('~/WebServices/AjaxService.asmx/GetStoreRecord'),
                data: "{'recordID':'" + recordID + "'}",
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function(res) {
                    if (res.d == null) return;
                    var store = normalizeStore(res.d);
                    td.setTemplateElement("detailsRowTemplate");
                    td.processTemplate(store);
                    td.addClass("Filled");
                    
                    //hide empty groups
                    $(".Group").each(function() {
						var isEmpty = true;
						$(".ItemValue", $(this)).each(function() {
							if (!$(this).is(":empty")) isEmpty = false;
						});
						if (isEmpty) {
							$(this).hide();
						}
                    });
                }
            });
        }
    }

    function normalizeStore(store) {
        var newStore = store;

        $.each(store.FixedFields, function(i, value) {
            newStore[i] = value;
        });

        $.each(store.VariableFields, function(i, item) {
            var key = item.Key.replace(/\s/g, "");
            newStore[key] = item.Value;
        });

        return newStore;
    }

    SLP.SetFieldValue = function(value, defaultValue) {
        return $.trim(value).toLowerCase() == 'true'
			? defaultValue
			: value;
    };


    var openMarker = null;

    SLP.OnCloseMarker = function() {
        if (openMarker != null) {
            openMarker.closeInfoWindow();
        }
    };

    var currTimeout = null;
    var mapMarkers = [];

    function LoadMarkers(stores) {

        if (typeof stores != 'undefined' && stores != null && stores.length > 0) {

            mapMarkers = [];

            for (var i = 0; i < stores.length; i++) {
                var LatLong = new GLatLng(stores[i].Latitude, stores[i].Longitude);
                if (LatLong != null) {
                    var iconUrl = SLP.GetIconUrl(stores[i].StoreType);
                    var options = {
                        hide: i >= ddlResultsPerPage,
                        icon: CreateIcon(iconUrl)
                    };
                    var marker = new GMarker(LatLong, options);
                    marker.num = i;
                    map.addOverlay(marker);
                    mapMarkers[mapMarkers.length] = marker;

                    GEvent.addListener(marker, "mouseover", function() {
                        this.openInfoWindowHtml(GetSmallStoreInfo(stores[this.num]));
                        openMarker = this;
                        if (currTimeout != null) clearTimeout(currTimeout);
                    });
                    GEvent.addListener(marker, "mouseout", function() {
                        currTimeout = setTimeout("Shoppers.Controls.StoreLocator.OnCloseMarker();", 4000);
                    });
                }
            }
			
			SLP.RenderView(0, stores.length);
        }
    };

    ///
    // Returns custom icon settings
    ///
    function CreateIcon(iconUrl) {
        var iconPath = opts.IconPath;
        var icon = new GIcon();
        icon.image = iconUrl;
        icon.shadow = iconPath + 'shadow.png';
        icon.iconSize = new GSize(30, 46);
        icon.shadowSize = new GSize(56, 46);
        icon.iconAnchor = new GPoint(15, 46);
        icon.infoWindowAnchor = new GPoint(11, 0);
        icon.printImage = iconPath + 'printImage.gif';
        icon.mozPrintImage = iconPath + 'mozPrintImage.gif';
        icon.printShadow = iconPath + 'printShadow.gif';
        icon.transparent = iconPath + 'transparent.png';
        icon.imageMap = [18, 0, 21, 1, 23, 2, 24, 3, 25, 4, 26, 5, 27, 6, 27, 7, 28, 8, 28, 9, 29, 10, 29, 11, 29, 12, 29, 13, 29, 14, 29, 15, 29, 16, 29, 17, 29, 18, 29, 19, 28, 20, 28, 21, 27, 22, 27, 23, 26, 24, 26, 25, 25, 26, 25, 27, 24, 28, 24, 29, 23, 30, 23, 31, 22, 32, 22, 33, 21, 34, 21, 35, 20, 36, 20, 37, 19, 38, 19, 39, 18, 40, 17, 41, 17, 42, 16, 43, 16, 44, 15, 45, 14, 45, 14, 44, 13, 43, 12, 42, 12, 41, 11, 40, 11, 39, 10, 38, 10, 37, 9, 36, 9, 35, 8, 34, 8, 33, 7, 32, 7, 31, 6, 30, 6, 29, 5, 28, 5, 27, 4, 26, 4, 25, 3, 24, 3, 23, 2, 22, 2, 21, 1, 20, 1, 19, 1, 18, 0, 17, 0, 16, 0, 15, 0, 14, 0, 13, 0, 12, 1, 11, 1, 10, 1, 9, 2, 8, 2, 7, 3, 6, 3, 5, 4, 4, 5, 3, 7, 2, 8, 1, 11, 0, 18, 0];
        return icon;
    };

    SLP.GetIconUrl = function(storeTypeName) {
        for (var i = 0; i < opts.StoreTypes.length; i++) {
            var storeType = opts.StoreTypes[i];
            if (storeType.Description.toLowerCase() == storeTypeName.toLowerCase()) {
                return storeType.IconUrl;
            }
        }
    };

    function GetSmallStoreInfo(store) {
        return "<b>" + store.Name + "</b><br/>"
            + store.Address + "<br/>" + store.City;
    };

})(Shoppers.Controls.StoreLocator, jQuery);


