/**
 * Class: Groomers
 * When activated, add groomer markers that, when clicked, add their path they
 * made.
 */
function Groomers(map, main, options) {
    this.checkbox = document.getElementById("groomersActivate");
    this.groomerMarkerType = null;

    OpenLayers.Util.extend(this, options);

    this.selectedMarker = null;
    this.groomerMarkers = [];
    this.groomerMarkersSmall = [];
    this.groomerPaths = [];
    this.map = map;
    this.main = main;
    this.querying = false;

    this.mapInfoWindowClose = GEvent.bind(this.map, "infowindowclose", this,
                                         this.onMapInfoWindowClose);
    this.mapZoomEnd = GEvent.bind(this.map, "zoomend", this, this.onMapZoomEnd);
};

/**
 * Method: isActive
 * Return if the groomer checkbox is checked.
 * 
 * Returns:
 * {Boolean}
 */
Groomers.prototype.isActive = function() {
    return this.checkbox.checked;
};

/**
 * Method: triggerRead
 *
 * Triggers the getFeatures function to get the conditions for the current 
 *     condition level.
 */
Groomers.prototype.triggerRead = function() {
    this.querying = true;
    var oOptions = {
        'extent': this.main.QCBBOX,
        'layer': "groomers_points",
        'level': 19
    };
    this.main.getFeatures(this.readGroomers, oOptions);
};

/**
 * Method: readGroomers
 * From a given GeoJSON ajax response, create groomer markers, put them in 
 *     an array and add them to the map.  Add some properties and events at the
 *     same time.
 *
 * Parameters:
 * doc - {AJAXResponse} The response from the AJAX query
 *
 * Returns:
 * {Array(<GOverlay>)}
 */
Groomers.prototype.readGroomers = function(doc) {
    var oMain = fcmq;
    var oGroomers = oMain.groomers;
    var aoMarkers = [];
    var myJsonData = eval('(' + doc + ')');
    var szStyle = oGroomers.groomerMarkerType;

    aoFeatures = myJsonData;

    for(var i=0; i<aoFeatures.length; i++){
        var oFeature = aoFeatures[i];
        var nId = oFeature.id;
        var aCoordinates = oFeature.geometry.coordinates;

        // normal marker
        var szClass = oFeature.properties[oMain.classProperty];
        var oStyle = oMain.getMarkerStyleObject(szStyle,szClass);
        var oIcon = new GIcon(oStyle);
        var oLatLng = new GLatLng(aCoordinates[1],aCoordinates[0]);
        var oMarker = new GMarker(
            oLatLng,{icon: oIcon, clickable: true, hide: true}
        );

        oMarker.main = oMain;
        oMarker.map = oMain.map;
        oMarker.properties = oFeature.properties;
        oMarker.id = nId;
        oMarker.defaultStyle = oStyle;
        oMarker.properties[oMain.styleProperty] = szStyle;

        GEvent.bind(oMarker, "click", oMarker, oGroomers.onGroomerMarkerClick);

        oGroomers.groomerMarkers.push(oMarker);
        oMain.map.addOverlay(oMarker);


        // small marker
        var szClass = 3;
        var oStyle = oMain.getMarkerStyleObject(szStyle,szClass);
        var oIcon = new GIcon(oStyle);
        var oLatLng = new GLatLng(aCoordinates[1],aCoordinates[0]);
        var oMarker = new GMarker(
            oLatLng,{icon: oIcon, clickable: true, hide: true}
        );

        oMarker.main = oMain;
        oMarker.map = oMain.map;
        oMarker.properties = oFeature.properties;
        oMarker.id = nId;
        oMarker.defaultStyle = oStyle;
        oMarker.properties[oMain.styleProperty] = szStyle;
        oMarker.isSmall = true;

        GEvent.bind(oMarker, "click", oMarker, oGroomers.onGroomerMarkerClick);

        oGroomers.groomerMarkersSmall.push(oMarker);
        oMain.map.addOverlay(oMarker);
    };

    oGroomers.onMapZoomEnd(0, oMain.map.getZoom());

    oMain.hidePleaseWait();
    oGroomers.querying = false;
};

/**
 * Method: triggerGroomerPathsRead
 *
 * Triggers the getFeatures function to get selected groomer paths (lines)
 */
Groomers.prototype.triggerGroomerPathsRead = function(oOptions) {
    this.querying = true;
    oOptions = oOptions || {};
    oOptions['extent'] = false;
    oOptions['layer'] = "groomers_lines";
    oOptions['level'] = 19;
    oOptions['style'] = 1;

    this.main.getFeatures(this.addGroomerPaths, oOptions);
};

/**
 * Method: addGroomerPaths
 * From a given GeoJSON ajax response, create lines that represent the selected
 *     groomer path taken.  More than one line can be returned.  Put them in 
 *     an array and add them to the map.  Add some properties.
 *
 * Parameters:
 * doc - {AJAXResponse} The response from the AJAX query
 *
 * Returns:
 * {Array(<GOverlay>)}
 */
Groomers.prototype.addGroomerPaths = function(doc) {
    var oMain = fcmq;
    var oGroomers = oMain.groomers;
    var aoGroomerPaths = oMain.readGeoJSON(doc);

    for(i=0; i<aoGroomerPaths.length; i++) {
        oGroomerPath = aoGroomerPaths[i];
        oMain.map.addOverlay(oGroomerPath);
        oGroomers.groomerPaths.push(oGroomerPath);
    }

    oMain.hidePleaseWait();
    oGroomers.querying = false;
};

/**
 * Method: onActivate
 * Called when the 'activate groomers' checkbox is checked.  Recenters the map
 *     and trigger the read of the groomers.
 */
Groomers.prototype.onActivate = function() {
    if(this.main.zoomToOnGroomersActivate) {
        var oLatLng = new GLatLng(this.main.groomersLat,this.main.groomersLng);
        this.map.setCenter(oLatLng,this.main.groomersZoom);
    }

    this.triggerRead(); 
};

/**
 * Method: onDeactivate
 * Called when the 'activate groomers' checkbox is unchecked.  Clear every 
 *     groomer markers.  If some groomer paths are also on the map, that means
 *     that there was one groomer marker selected, so clear the paths and remove
 *     the infoWindow.
 */
Groomers.prototype.onDeactivate = function() {
    this.closePopup();
    this.clearGroomers();
    if(this.getSelectedMarker()) {
        this.map.closeInfoWindow();
        this.clearGroomerPaths();
    }
};

/**
 * Method: onDeactivate
 * Called when the 'activate groomers' checkbox status is changed.  Trigger the
 *     according event (checked or unchecked).
 */
Groomers.prototype.onCheckBoxChange = function() {
    if(this.isActive()){
        this.onActivate();
    } else {
        this.onDeactivate();
    }
};

/**
 * Method: clearGroomers
 * Removes all groomer markers (normal and small) from the map and 
 * reinitialize the arrays.
 */
Groomers.prototype.clearGroomers = function() {
    for(var i=0; i<this.groomerMarkers.length; i++) {
        this.map.removeOverlay(this.groomerMarkers[i]);
    }
    this.groomerMarkers = [];

    for(var i=0; i<this.groomerMarkersSmall.length; i++) {
        this.map.removeOverlay(this.groomerMarkersSmall[i]);
    }
    this.groomerMarkersSmall = [];
};

/**
 * Method: clearGroomerPaths
 * Removes all groomer markers from the mapand reinitialize the array.
 */
Groomers.prototype.clearGroomerPaths = function() {
    for(var i=0; i<this.groomerPaths.length; i++) {
        this.map.removeOverlay(this.groomerPaths[i]);
    }
    this.groomerPaths = [];
};

/**
 * Method: onGroomerMarkerClick
 * Called when a groomer marker is clicked.  Open the infoWindow with the 
 *     groomer informations and trigger the groomer path request.
 *
 * If the application is already querying for groomer features, don't do
 * anything.
 *
 * Parameters:
 * oPoint   - {<GPoint>} A point object with pixel coordinates.
 */
Groomers.prototype.onGroomerMarkerClick = function(oPoint) {
    if(this.main.groomers.querying === true) {
        return;
    }
    
    this.main.groomers.openGroomerInfoWindow(this, oPoint);
    var oOptions = {'moreValues': this.id, 'moreValueField': '4'};
    this.main.groomers.triggerGroomerPathsRead(oOptions);
};

/**
 * Method: openGroomerInfoWindow
 * From a given groomer marker, open an infoWindow popup that contains some
 *     information about it.
 *
 * Parameters:
 * oMarker   - {<GMarker>} The marker to open the infoWindow onto
 * oPoint   - {<GPoint>} A point object with pixel coordinates.
 */
Groomers.prototype.openGroomerInfoWindow = function(oMarker, oPoint) {
    var szLang = oMarker.main.lang;
    var oLang = lang[szLang];

    // if an other groomer marker is currently clicked, close it first
    if(this.getSelectedMarker()) {
        this.closePopup();
    }

    this.main.otherOverlayInfoWindow = true;

    // keep track of the selected marker and highlight it
    this.selectedMarker = oMarker;
    this.highlightMarker(oMarker);

    // Date 'from'
    var szDateFrom = oMarker.properties[oMarker.main.groomerProperties['datefrom']];
    aoDateFrom = szDateFrom.split('-');
    var oDate = new Date(aoDateFrom[0],aoDateFrom[1]-1,aoDateFrom[2]);
    szDateFrom = (szLang == 'fr')? oDate.toLongFrenchFormat() : oDate.toLongEnglishFormat();

    // Date 'to'
    var szDateTo = oMarker.properties[oMarker.main.groomerProperties['dateto']];
    aoDateTo = szDateTo.split('-');
    var oDate = new Date(aoDateTo[0],aoDateTo[1]-1,aoDateTo[2]);
    szDateTo = (szLang == 'fr')? oDate.toLongFrenchFormat() : oDate.toLongEnglishFormat();

    // Hours
    var szHourFrom = oMarker.properties[oMarker.main.groomerProperties['hourfrom']];
    var szHourTo = oMarker.properties[oMarker.main.groomerProperties['hourto']];

    // full strings
    var szFrom = oLang['groomerFrom']+szDateFrom+oLang['groomerAt']+szHourFrom;
    var szTo = oLang['groomerTo']+szDateTo+oLang['groomerAt']+szHourTo;

    // div container
    var oContainer = document.getElementById("groomerInfoWindow");

    var oTable = document.createElement("table");

    // last row (text)
    oRow = oTable.insertRow(0);
    oCell = oRow.insertCell(0);
    oCell.className = "serviceInfoWindowText";

    oTextNode = document.createTextNode(szFrom);
    oCell.appendChild(oTextNode);

    oBr = document.createElement("br");
    oCell.appendChild(oBr);

    oTextNode = document.createTextNode(szTo);
    oCell.appendChild(oTextNode);
	
    // add the table to the div
    oContainer.appendChild(oTable);

    var oPopup = document.getElementById("divGroomerPopupMenu");
    hideDiv(oPopup, false);
};

/**
 * Method: onMapInfoWindowClose
 * Called when a InforWindow is closed.  Reset InfoWindow flags.
 */
Groomers.prototype.onMapInfoWindowClose = function() {
    this.clearGroomerPaths();
};

/**
 * Method: closePopup
 * Called when a the [X] button of the popup is clicked or if an other marker
 * is clicked.  Close the Popup, unselect current marker (unhighlighting it).
 */
Groomers.prototype.closePopup = function() {
    if(this.getSelectedMarker()) {
        this.main.otherOverlayInfoWindow = false;

        if(this.selectedMarker) {
            this.unhighlightMarker(this.selectedMarker);
            this.selectedMarker = null;
        }

        var oPopup = document.getElementById("divGroomerPopupMenu");
        hideDiv(oPopup, true);

        var oContainer = document.getElementById("groomerInfoWindow");
        oContainer.removeChild(oContainer.lastChild);

        this.onMapInfoWindowClose();
    }
};

/**
 * Method: highlightMarker
 * Change the image of the marker to a specific style.
 */
Groomers.prototype.highlightMarker = function(oMarker) {
    var oStyle = this.main.getMarkerStyleObject(
        this.groomerMarkerType, oMarker.isSmall ? 4 : 2
    );
    oMarker.setImage(oStyle['image']);

    // highlight sibling marker as well
    var oSiblingMarker = this.getSiblingMarker(oMarker);
    var oStyle = this.main.getMarkerStyleObject(
        this.groomerMarkerType, oSiblingMarker.isSmall ? 4 : 2
    );
    oSiblingMarker.setImage(oStyle['image']);
};

/**
 * Method: unhighlightMarker
 * Restore the style of the marker to its default value
 */
Groomers.prototype.unhighlightMarker = function(oMarker) {
    oMarker.setImage(oMarker.defaultStyle['image']);

    // unhighlight sibling marker as well
    var oSiblingMarker = this.getSiblingMarker(oMarker);
    oSiblingMarker.setImage(oSiblingMarker.defaultStyle['image']);
};

/**
 * Method: getSelectedMarker
 * Get the current selected marker
 */
Groomers.prototype.getSelectedMarker = function() {
    return this.selectedMarker;
};

/**
 * Method: onMapZoomEnd
 * Called when the map level changes.  
 *     Toggle the 'groomers' and 'smallGroomers' marker accordingly to the
 *     new and old zoom levels.
 *
 * Parameters:
 * nOldLevel - {Integer} The previous map level
 * nNewLevel - {Integer} The new map level
 */
Groomers.prototype.onMapZoomEnd = function(nOldLevel, nNewLevel) {
    var nMinZoom = this.main.groomersMinZoom;
    var nSwapZoom = this.main.groomersSwapZoom;

    if (nNewLevel < nMinZoom) {
        if (nOldLevel >= nMinZoom) {
            this.hideSmallGroomers();
        }
        if (nOldLevel >= nSwapZoom) {
            this.hideGroomers();
        }
    } else if (nNewLevel < nSwapZoom) {
        if (nOldLevel < nMinZoom || nOldLevel >= nSwapZoom) {
            this.showSmallGroomers();
        }
        if (nOldLevel >= nSwapZoom) {
            this.hideGroomers();
        }
    } else {
        if (nOldLevel < nSwapZoom) {
            this.showGroomers();
            this.hideSmallGroomers();
        }
    }
};

/**
 * Method: showGroomers
 * Show the normal groomer markers.
 */
Groomers.prototype.showGroomers = function() {
    for(var i=0, len=this.groomerMarkers.length; i<len; i++) {
        this.groomerMarkers[i].show();
    }
};

/**
 * Method: hideGroomers
 * Hide the normal groomer markers.
 */
Groomers.prototype.hideGroomers = function() {
    for(var i=0, len=this.groomerMarkers.length; i<len; i++) {
        this.groomerMarkers[i].hide();
    }
};

/**
 * Method: showSmallGroomers
 * Show the small groomer markers.
 */
Groomers.prototype.showSmallGroomers = function() {
    for(var i=0, len=this.groomerMarkersSmall.length; i<len; i++) {
        this.groomerMarkersSmall[i].show();
    }
};

/**
 * Method: hideSmallGroomers
 * Hide the small groomer markers.
 */
Groomers.prototype.hideSmallGroomers = function() {
    for(var i=0, len=this.groomerMarkersSmall.length; i<len; i++) {
        this.groomerMarkersSmall[i].hide();
    }
};

/**
 * Method: getSiblingMarker
 * Returns the sibling marker of a given marker, i.e. if it's a small marker, 
 *    find and return the normal one and vice versa.
 *
 * Parameters:
 * oMarker   - {<GMarker>} The marker to get the sibling from using its id
 *
 * Returns:
 * {<GMarker>} The sibling marker having the same id as the defined marker
 */
Groomers.prototype.getSiblingMarker = function(oMarker) {
    var aOtherMarkers = (oMarker.isSmall)
        ? this.groomerMarkers : this.groomerMarkersSmall;

    for (var i=0, len=aOtherMarkers.length; i<len; i++) {
        if (aOtherMarkers[i].id == oMarker.id) {
            return aOtherMarkers[i];
        }
    }

    return false;
};

