﻿
///////////////////////////zmienne//////////////////////////////////
        var selectionMode = 0; //1 tryb zaznaczania 
        var selectionType = 0; //1- kwadret, 2- kolo, 3- polygon
        var map = null;
        var locations = [];
        var handlers = [];
        var pushPinHandlers = [];
        var infoBoxHandlers = [];
        var idTable = [];
        var infoBoxContentTable = [];

//////////////////////////ogolne////////////////////////////////////

        //metoda ogolnie sprawdzajaca czy mapa wlaczona
        function CheckMapStart(){
            var mapVisible = this.document.getElementById("ucMainSearchBox_mapVisible");
            
            if(mapVisible.value == 1){
                GetMap();
            }
            else{
               CloseMap();
            }
        }

        function HandleMapButtonEvent(){
                if(map == null){
                    GetMap();
                }
                else{
                    CloseMap();
                }
        }

        function GetMap() {

            map = new Microsoft.Maps.Map(document.getElementById("mapDiv"),
                           { credentials: "AmUq1h3devQESU7xayilCJe8TmprdDEeTWHCHMeFN8f5maBOxeeb8N4JI4oAa3PS",
                               enableSearchLogo: false,
                               enableClickableLogo: false,
                               center: new Microsoft.Maps.Location(52.5, 19.5),
                               //mapTypeId: Microsoft.Maps.MapTypeId.road,
                               //showDashboard: false,
                               showMapTypeSelector: false,
                               showScalebar: false,
                               zoom: 6,
                               inertiaIntensity: .5,
                               tileBuffer: 1
                           });
                  
                  
            //ustawiamy ustawienia mapy         
            var mapDiv = this.document.getElementById("searchMap");
            var mapVisible = this.document.getElementById("ucMainSearchBox_mapVisible");
            var mapZoom = this.document.getElementById("ucMainSearchBox_mapZoom");
            var mapCenter = this.document.getElementById("ucMainSearchBox_mapCenter");
            
            if(window.navigator.userAgent.indexOf ( "MSIE" )<=0){
                mapDiv.style.display = 'block'; 
            }else{
                //if(mapDiv.style.display == 'none'){
                    mapDiv.style.display="";
                //}
                mapDiv.style.height = "430px";
            }
            mapVisible.value = 1;
            
            if(mapZoom.value != "" && mapZoom.value != "0" && mapCenter.value != "" && mapCenter.value != "0"){
                var centerLocations = mapCenter.value.split(";");
                if(centerLocations.length ==2){
                    map.setView({zoom: parseInt(mapZoom.value), center: new Microsoft.Maps.Location(Number(centerLocations[0]), Number(centerLocations[1]))});
                }
            }
            


            var pinsField = this.document.getElementById("ucMainSearchBox_pins");
            if (pinsField != null)
                if (pinsField.value != "")
                    SelectPins(pinsField.value);
                    
                    
            var offersIdTable = this.document.getElementById("ucMainSearchBox_offersIdTable");
            if(offersIdTable != null)
                if(offersIdTable.value != "")
                    InitOffersIdTable(offersIdTable.value);
        }

        function CloseMap() {

            if (typeof (map) != 'undefined' && map != null) {
                map.dispose();
                map = null;
            }
            
            //zamykamy ustawienia mapy         
            var mapDiv = this.document.getElementById("searchMap");
            var mapVisible = this.document.getElementById("ucMainSearchBox_mapVisible");
            var mapZoom = this.document.getElementById("ucMainSearchBox_mapZoom");
            var mapCenter = this.document.getElementById("ucMainSearchBox_mapCenter");
            
            if(window.navigator.userAgent.indexOf ( "MSIE" )<=0){
                mapDiv.style.display = "none"; 
            }
            else{
                mapDiv.style.height = 0;
            }
            mapVisible.value = 0;
            mapZoom.value = 0;
            mapCenter.value = 0;
            
            //usuwamy zdarzenia
            CleanEvents();
            CleanPushpinEvents();
            
        }

        function CleanSelection(){
            for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                var polygon = map.entities.get(i);
                if (polygon instanceof Microsoft.Maps.Polygon) {
                    map.entities.removeAt(i);
                }
            }
            locations = [];
        }

        function CleanEvents() {
            for (var i = handlers.length - 1; i >= 0; i--) {
                Microsoft.Maps.Events.removeHandler(handlers[i]);
            }
            handlers = [];
        }
        
        function CleanPushpinEvents() {
            for (var i = pushPinHandlers.length - 1; i >= 0; i--) {
                Microsoft.Maps.Events.removeHandler(pushPinHandlers[i]);
            }
            pushPinHandlers = [];
        }
        
        function CleanInfoboxEvents() {
            for (var i = infoBoxHandlers.length - 1; i >= 0; i--) {
                Microsoft.Maps.Events.removeHandler(infoBoxHandlers[i]);
            }
            infoBoxHandlers = [];
        }
        
        function InitOffersIdTable(offersIdTableString){
            try{
                var offersIdTable = offersIdTableString.split("&");

                for (var i = offersIdTable.length - 1; i >= 0; i--) {

                    var offerId = offersIdTable[i].split(";");
                    if (offerId.length == 2) {
                        idTable[offerId[0]]= offerId[1];
                    }
                }
            }
            catch(err){
            
            }
        }
        
        ///////////////////// pushpins////////////////////////////////////////

        function SelectPins(selectedLocationString) {
            try {
                var selectedLocations = selectedLocationString.split("&");

                for (var i = selectedLocations.length - 1; i >= 0; i--) {

                    var selectedLocation = selectedLocations[i].split(";");
                    if (selectedLocation.length == 2) {
                        var loc = new Microsoft.Maps.Location(selectedLocation[0], selectedLocation[1]);
                        var pushpin = new Microsoft.Maps.Pushpin(loc, null)
                        pushPinHandlers.push(Microsoft.Maps.Events.addHandler(pushpin, 'mouseover', ShowPushpinInfo));
                        map.entities.push(pushpin);
                    }
                }
            }
            catch (err) {
            }
        }

        function CleanPushPins(){
            for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                var pushpin = map.entities.get(i);
                if (pushpin instanceof Microsoft.Maps.Pushpin) {
                    map.entities.removeAt(i);
                }
            }
            
            CleanPushpinEvents();
        }

        function ShowPushpinInfo(e){
            if (e.targetType == 'pushpin') {
                try{
           
                    var pushpin = e.target;
                    var guid = idTable[pushpin.getLocation().latitude+''+pushpin.getLocation().longitude];
                    if(guid!=''){
                        var body;
                        if(infoBoxContentTable[guid] == null){
                            var url = "http://" +document.domain+"/getinfoboxcontent.aspx?id="+guid ;
                            //var url = "http://" +"localhost:1645"+"/getinfoboxcontent.aspx?id="+guid ;
                            if (window.XMLHttpRequest)
                            {// code for IE7+, Firefox, Chrome, Opera, Safari
                                xmlhttp=new XMLHttpRequest();
                            }
                            else
                            {// code for IE6, IE5
                                xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                            }
                            xmlhttp.open("GET",url,false);
                            xmlhttp.send();
                            if(xmlhttp.status != "404"){
                                if(body != ''){
                                    body = xmlhttp.responseText; 
                                }
                            }
                        }
                        else{
                            body = infoBoxContentTable[guid];
                        }
                        
                        if(body != ''){
                            var infoBox = new Microsoft.Maps.Infobox(pushpin.getLocation(), {
                                visible: true,
                                htmlContent: body,
                                width: 150,
                                heigt: 60, 
                                offset: new Microsoft.Maps.Point(-15,115)
                                });
                       }
                    }

                    //czyscimy infoboxy
                    HidePushpinInfo();

                    //dodajemy info box
                    infoBoxHandlers.push(Microsoft.Maps.Events.addHandler(infoBox, 'mouseleave', HidePushpinInfo));
                    map.entities.push(infoBox);
                }
                catch (err){
                
                }
            }
            
        }
        
        function HidePushpinInfo(){
            
            //czyscimy mape
             for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                var infoBox = map.entities.get(i);
                if (infoBox instanceof Microsoft.Maps.Infobox) {
                    map.entities.removeAt(i);
                }
            }
            //czyscimy zdarzenia
            CleanInfoboxEvents();
        }

        /////////////////////////////zaznaczanie prostokat/////////////////////////////////

        function SelectRectangle() {
            //czyscimy
            locations = [];
            //czyscimy z polygonow
            for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                var polygon = map.entities.get(i);
                if (polygon instanceof Microsoft.Maps.Polygon) {
                    map.entities.removeAt(i);
                }
            }

            //ustawiamny flage
            selectionMode = 1;
            selectionType = 1;

            //czyscimy eventy
            CleanEvents();
            //ustawiamy event
            handlers.push(Microsoft.Maps.Events.addHandler(map, 'click', AddRectangleLocation));
        }

        function AddRectangleLocation(e) {
            if (e.targetType == "map" || e.targetType == "polygon") {
                if (selectionMode == 1 && selectionType == 1) {

                    var point = new Microsoft.Maps.Point(e.getX(), e.getY());
                    var loc = map.tryPixelToLocation(point);
                    locations.push(loc);

                    switch (locations.length) {
                        case 1:
                            //Microsoft.Maps.Events.addHandler(map, 'rightclick', ShowRectAnglePreview);
                            handlers.push(Microsoft.Maps.Events.addHandler(map, 'mousemove', ShowRectAnglePreview));
                            break;
                        case 2:
                            //znaczy sie ze klikna w danym miejscu
                            //przekopiowac dane do lacations
                            for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                                var polygon = map.entities.get(i);
                                if (polygon instanceof Microsoft.Maps.Polygon) {
                                    locations = polygon.getLocations();
                                    break;
                                }
                            }
                            selectionMode = 0;
                            CleanEvents();
                            break;
                        default:
                            selectionMode = 0;
                            CleanEvents();
                            //nie powinien nigdy tu sie dostac!
                            break;
                    }
                }
            }
        }

        function ShowRectAnglePreview(e) {
            if (e.targetType == "map" || e.targetType == "polygon") {
                if (locations.length == 1) {

                    //zaznaczone miejsce
                    var loc = map.tryPixelToLocation(new Microsoft.Maps.Point(e.getX(), e.getY()));

                    //tmp lista
                    var rectangleLocations = [];
                    rectangleLocations[0] = locations[0];
                    rectangleLocations[1] = new Microsoft.Maps.Location(loc.latitude, locations[0].longitude);
                    rectangleLocations[2] = loc;
                    rectangleLocations[3] = new Microsoft.Maps.Location(locations[0].latitude, loc.longitude);
                    rectangleLocations[4] = locations[0];

                    //wyczyscic mape
                    for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                        var polygon = map.entities.get(i);
                        if (polygon instanceof Microsoft.Maps.Polygon) {
                            map.entities.removeAt(i);
                            break;
                        }
                    }

                    //dodac poligon
                    var newPolygon = new Microsoft.Maps.Polygon(rectangleLocations, { fillColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                        strokeColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                        strokeThickness: 2
                    });
                    map.entities.push(newPolygon);

                    //dodanie eventu zeby po polygonie tez sie dalo
                    handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'mousemove', ShowRectAnglePreview));
                    handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'click', AddRectangleLocation));
                }
            }
        }

        /////////////////////////////zaznaczanie kolo/////////////////////////////////

        function SelectCircle() {
            //czyscimy
            locations = [];
            //czyscimy z polygonow
            for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                var polygon = map.entities.get(i);
                if (polygon instanceof Microsoft.Maps.Polygon) {
                    map.entities.removeAt(i);
                }
            }

            //ustawiamny flage
            selectionMode = 1;
            selectionType = 2;

            //czyscimy eventy
            CleanEvents();
            //ustawiamy event
            handlers.push(Microsoft.Maps.Events.addHandler(map, 'click', AddCircleLocation));
        }

        function AddCircleLocation(e) {
            if (e.targetType == "map" || e.targetType == "polygon") {
                if (selectionMode == 1 && selectionType == 2) {

                    var point = new Microsoft.Maps.Point(e.getX(), e.getY());
                    var loc = map.tryPixelToLocation(point);
                    locations.push(loc);

                    switch (locations.length) {
                        case 1:
                            //Microsoft.Maps.Events.addHandler(map, 'rightclick', ShowRectAnglePreview);
                            handlers.push(Microsoft.Maps.Events.addHandler(map, 'mousemove', ShowCirclePreview));
                            break;
                        case 2:
                            //znaczy sie ze klikna w danym miejscu
                            //przekopiowac dane do lacations
                            for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                                var polygon = map.entities.get(i);
                                if (polygon instanceof Microsoft.Maps.Polygon) {
                                    locations = polygon.getLocations();
                                    break;
                                }
                            }
                            selectionMode = 0;
                            CleanEvents();
                            break;
                        default:
                            selectionMode = 0;
                            CleanEvents();
                            //nie powinien nigdy tu sie dostac!
                            break;
                    }
                }
            }
        }

        function ShowCirclePreview(e) {
            if (e.targetType == "map" || e.targetType == "polygon") {
                if (locations.length == 1) {

                    //zaznaczone miejsce
                    var loc = map.tryPixelToLocation(new Microsoft.Maps.Point(e.getX(), e.getY()));

                    //promien
                    var radius = GetCircleRadius(locations[0], loc);

                    //wyczyscic mape
                    for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                        var polygon = map.entities.get(i);
                        if (polygon instanceof Microsoft.Maps.Polygon) {
                            map.entities.removeAt(i);
                        }
                    }

                    //dodac poligon
                    var newPolygon = new Microsoft.Maps.Polygon(GetCircleLocations(locations[0], radius), { fillColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                        strokeColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                        strokeThickness: 2
                    });
                    map.entities.push(newPolygon);

                    //dodanie eventu zeby po polygonie tez sie dalo
                    handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'mousemove', ShowRectAnglePreview));
                    handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'click', AddCircleLocation));
                }
            }
        }

        function GetCircleRadius(location1, location2) {
            var lat1 = location1.latitude;
            var lon1 = location1.longitude;
            var lat2 = location2.latitude;
            var lon2 = location2.longitude;
            var earthRadius = 6371; //appxoximate radius in miles

            var factor = Math.PI / 180;
            var dLat = (lat2 - lat1) * factor;
            var dLon = (lon2 - lon1) * factor;
            var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * factor)
				* Math.cos(lat2 * factor) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
            var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            var d = earthRadius * c;

            return d;
        }

        function GetCircleLocations(loc, radius) {
            var R = 6371; // earth's mean radius in km
            var lat = (loc.latitude * Math.PI) / 180; //rad
            var lon = (loc.longitude * Math.PI) / 180; //rad
            var d = parseFloat(radius) / R;  // d = angular distance covered on earth's surface
            var locations = new Array();
            for (x = 0; x <= 360; x++) {
                var p2 = new Microsoft.Maps.Location(0, 0)
                brng = x * Math.PI / 180; //rad
                p2.latitude = Math.asin(Math.sin(lat) * Math.cos(d) + Math.cos(lat) * Math.sin(d) * Math.cos(brng));
                p2.longitude = ((lon + Math.atan2(Math.sin(brng) * Math.sin(d) * Math.cos(lat), Math.cos(d) - Math.sin(lat) * Math.sin(p2.latitude))) * 180) / Math.PI;
                p2.latitude = (p2.latitude * 180) / Math.PI;
                locations.push(p2);
            }
            return locations;
        }

        /////////////////////////////zaznaczanie poligonow/////////////////////////////////

        function SelectPolygon() {
            //czyscimy
            locations = [];
            //czyscimy z polygonow
            for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                var polygon = map.entities.get(i);
                if (polygon instanceof Microsoft.Maps.Polygon) {
                    map.entities.removeAt(i);
                }
            }

            //ustawiamny flage
            selectionMode = 1;
            selectionType = 3;

            //czyscimy eventy
            CleanEvents();
            //ustawiamy event
            handlers.push(Microsoft.Maps.Events.addHandler(map, 'click', AddPolygonLocation));
        }

        function AddPolygonLocation(e) {
            //dzieki dodaniu polygon mozna robic wklese zaznaczenia
            if (e.targetType == "map" || e.targetType == "polygon") {
                if (selectionMode == 1 && selectionType == 3) {

                    var point = new Microsoft.Maps.Point(e.getX(), e.getY());
                    var loc = map.tryPixelToLocation(point);
                    locations.push(loc);

                    switch (locations.length) {
                        case 1:
                            //tutaj nic
                            break;
                        case 2:
                            //tu juz mozna preview dawac
                            handlers.push(Microsoft.Maps.Events.addHandler(map, 'mousemove', ShowPolygonPreview));
                            //handlers.push(Microsoft.Maps.Events.addHandler(map, 'rightclick', ClosePolygonSelection));
                            handlers.push(Microsoft.Maps.Events.addHandler(map, 'keydown',ClosePolygonSelection2));
                            //handlers.push(Microsoft.Maps.Events.addHandler(map, 'keypress',ClosePolygonSelection2));
                            break;
                        default:
                            //tutaj wiecej niz 2, a wiec mozna kopiowac lokalizacje 
                            for (var i = map.entities.getLength() - 1; i >= 0; i--) {
                                var polygon = map.entities.get(i);
                                if (polygon instanceof Microsoft.Maps.Polygon) {
                                    locations = polygon.getLocations();
                                    break;
                                }
                            }
                            //bez ostatniej, jesli jest to kopia pierwszej (bo wtedy polygon sie miesza)
                            if (locations[0].latitude == locations[locations.length - 1].latitude && locations[0].longitude == locations[locations.length - 1].longitude)
                                locations.pop();
                            break;
                    }
                }
            }
        }

        function ShowPolygonPreview(e) {
            if (e.targetType == "map" || e.targetType == "polygon") {

                //zaznaczone miejsce
                var loc = map.tryPixelToLocation(new Microsoft.Maps.Point(e.getX(), e.getY()));

                //tmp lista
                var polygonLocations = [];
                for (var i = 0; i <= locations.length - 1; i++) {
                    polygonLocations.push(locations[i]);
                }
                //dodajmey nowy
                polygonLocations.push(loc);

                //na koniec domykamy
                polygonLocations.push(polygonLocations[0]);

                //wyczyscic mape
                for (i = map.entities.getLength() - 1; i >= 0; i--) {
                    var polygon = map.entities.get(i);
                    if (polygon instanceof Microsoft.Maps.Polygon) {
                        map.entities.removeAt(i);
                        break;
                    }
                }

                //dodac poligon
                var newPolygon = new Microsoft.Maps.Polygon(polygonLocations, { fillColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                    strokeColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                    strokeThickness: 2
                });
                map.entities.push(newPolygon);

                //dodanie eventu zeby po polygonie tez sie dalo
                handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'mousemove', ShowPolygonPreview));
                handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'click', AddPolygonLocation));
                //handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'rightclick', ClosePolygonSelection));
                handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'keydown',ClosePolygonSelection2));
                //handlers.push(Microsoft.Maps.Events.addHandler(newPolygon, 'keypress',ClosePolygonSelection2));
            }
        }

        function ClosePolygonSelection(e) {
            if (e.targetType == "map" || e.targetType == "polygon") {

                //zaznaczone miejsce
                var loc = map.tryPixelToLocation(new Microsoft.Maps.Point(e.getX(), e.getY()));

                //tmp lista
                var polygonLocations = [];
                for (var i = 0; i <= locations.length - 1; i++) {
                    polygonLocations.push(locations[i]);
                }
                //dodajmey nowy
                polygonLocations.push(loc);

                //na koniec domykamy
                polygonLocations.push(polygonLocations[0]);

                //wyczyscic mape
                for (i = map.entities.getLength() - 1; i >= 0; i--) {
                    var polygon = map.entities.get(i);
                    if (polygon instanceof Microsoft.Maps.Polygon) {
                        map.entities.removeAt(i);
                        break;
                    }
                }

                //dodac poligon
                var newPolygon = new Microsoft.Maps.Polygon(polygonLocations, { fillColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                    strokeColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                    strokeThickness: 2
                });
                map.entities.push(newPolygon);

                //zapisac lokalizacje
                locations = polygonLocations;

                //zamykamy zaznaczenia
                selectionMode = 0;
                CleanEvents();
            }
        }
        
        function ClosePolygonSelection2(e){
                if(e.keyCode == "27"){
                    //zaznaczone miejsce na podstweie narysowanego polygonu
                    var loc;
                    for (i = map.entities.getLength() - 1; i >= 0; i--) {
                        var polygon = map.entities.get(i);
                        if (polygon instanceof Microsoft.Maps.Polygon) {
                            var polygonLocations1 = polygon.getLocations();
                            if(polygonLocations1.length >= 2){
                                loc = polygonLocations1[polygonLocations1.length -2];
                            }
                            else{
                                loc = map.getTargetCenter();
                            }
                            break;
                        }
                    }
                    //var loc = map.tryPixelToLocation(new Microsoft.Maps.Point(e.getX(), e.getY()));

                    //tmp lista
                    var polygonLocations = [];
                    for (var i = 0; i <= locations.length - 1; i++) {
                        polygonLocations.push(locations[i]);
                    }
                    //dodajmey nowy
                    polygonLocations.push(loc);

                    //na koniec domykamy
                    polygonLocations.push(polygonLocations[0]);

                    //wyczyscic mape
                    for (i = map.entities.getLength() - 1; i >= 0; i--) {
                        var polygon1 = map.entities.get(i);
                        if (polygon1 instanceof Microsoft.Maps.Polygon) {
                            map.entities.removeAt(i);
                            break;
                        }
                    }

                    //dodac poligon
                    var newPolygon = new Microsoft.Maps.Polygon(polygonLocations, { fillColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                        strokeColor: new Microsoft.Maps.Color(100, 100, 0, 100),
                        strokeThickness: 2
                    });
                    map.entities.push(newPolygon);

                    //zapisac lokalizacje
                    locations = polygonLocations;

                    //zamykamy zaznaczenia
                    selectionMode = 0;
                    CleanEvents();
                }
        }

        /////////////////////////////building query/////////////////////////////////

        function BuildQuery() {
            var queryValue;
            for (i = locations.length - 1; i >= 0; i--) {
                queryValue += '(' + locations[i].latitude + ';' + locations[i].longitude + ')';
            }

            var queryField = this.document.getElementById("ucMainSearchBox_query");
            queryField.value = queryValue;

            var selectionField = this.document.getElementById("ucMainSearchBox_selectionType");
            selectionField.value = selectionType;
            
            
            //i zapisz ustawienia mapy
            var mapZoom = this.document.getElementById("ucMainSearchBox_mapZoom");
            var mapCenter = this.document.getElementById("ucMainSearchBox_mapCenter");
            
            mapZoom.value = map != null ? map.getZoom() : 6;
            mapCenter.value = map!= null ? map.getCenter().latitude + ';' + map.getCenter().longitude : '52.5;19.5';
        }
        

        /////////////////////////////////////////////////////////////////////
        
        

        
