/**
 * Marqueur utilisé sur la carte interactive Toulouseweb.
 * Chaque marqueur est associé à une carte GSV et réagit aux événements
 * de zoom et déplacement. Le marqueur implémente le pattern observateur
 * et est un écouteur pour ces deux événements. Il s'ajoute lui même à la
 * liste des écouteurs nécessaires.
 * Une image (icône) est utilisée pour afficher le marqueur sur la carte,
 * par défaut celle-ci sera interprétée comme ayant son centre en bas au milieu.
 * C'est à dire que, pour des coordonnées données, l'icône du marqueur se placera
 * juste au dessus et horizontalement centrée.
 *
 * Bugs connus :
 *   - sur une carte qui n'est pas en plein écran (pleine largeur suffirait ?)
 *     le redimensionnement de la fenêtre donne des fausses coordonnées aux nouveaux marqueurs
 *
 * TODO :
 *   - affichage d'une popup avec nom, description
 *
 * @author Alan Macé
 *
 * @param GSV     gsv    l'objet GSV utilisé pour afficher la carte
 * @param Integer x      ordonnée du marqueur
 * @param Integer y      abscisse du marqueur
 * @param String  image  chemin vers l'image (ou icône) représentant le marqueur
 * @param Integer width  la largeur de l'image
 * @param Integer height la hauteur de l'image
 * @param Integer zoom   le niveau de zoom du marqueur correspondant aux coordonnées
 *                       (par défaut = gsv.zoomLevel)
 */
function Marker(gsv, x, y, image, width, height, zoom) {
    this.gsv = gsv;
    this.x = parseInt(x) + Math.floor(width / 2); // centrage horizontal de l'icône
    this.y = parseInt(y) + height;                // décalage vertical de l'icône
    this.width = width;
    this.height = height;
    this.zoomLevel = this.gsv.zoomLevel;

    this.element = document.createElement('img');
    this.element.setAttribute('src', image);
    this.element.className = 'marker_icon';
    this.element.style.position = 'absolute';
    this.element.style.width = this.width + 'px';
    this.element.style.height = this.height + 'px';
    this.element.style.zIndex = '100';
    document.getElementById('viewer').appendChild(this.element);

    this.gsv.addViewerMovedListener(this);
    this.gsv.addViewerZoomedListener(this);

    if (zoom) {
        if (this.gsv.zoomLevel - zoom < 0) {
            this.x +=  Math.floor(this.width / 2) * Math.pow(2, zoom - this.gsv.zoomLevel);
            this.y +=  this.height * Math.pow(2, zoom - this.gsv.zoomLevel);
        }
        this.x = this.x / Math.pow(2, zoom - this.gsv.zoomLevel);
        this.y = this.y / Math.pow(2, zoom - this.gsv.zoomLevel);
        
        if (zoom === this.gsv.zoomLevel) {
            // correction du positionnement
            this.x += Math.floor(this.width / 2);
            this.y += this.height;
        }
    }

    // calcul des coordonnées max
    this.coordsAtMaxZoom = {x: x, y: y};
    if (zoom === undefined) {
        for (var i = this.zoomLevel; i < this.gsv.maxZoomLevel; i++) {
            this.coordsAtMaxZoom.x *= 2;
            this.coordsAtMaxZoom.y *= 2;
        }
        this.coordsAtMaxZoom.x -= Math.floor(width / 2);
        this.coordsAtMaxZoom.y -= height;
    }

    this.position();
}

Marker.prototype = {
    /**
     * (Re)positionne le marqueur en fonction d'un moveEvent si la carte
     * a été déplacée et en fonction du GSV sinon
     */
    position: function(moveEvent) {
        if (moveEvent) {
            var ref = moveEvent;
        } else {
            var ref = this.gsv;
        }
        this.element.style.display = 'block';
        this.element.style.left = -parseInt(this.x - ref.x) + 'px';
        this.element.style.top = -parseInt(this.y - ref.y) + 'px';
    },

    /**
     * Notificateur de déplacement de la carte
     */
    viewerMoved: function(moveEvent) {
        this.position(moveEvent);
    },

    /**
     * Notificateur de zoom de la carte
     * Les nouvelles coordonnées sont calculées
     * puis le marqueur est repositionné
     */
    viewerZoomed: function(zoomEvent) {
        if (zoomEvent.level - this.zoomLevel < 0) {
            this.x +=  Math.floor(this.width / 2);
            this.y +=  this.height;
        }

        this.x = this.x / Math.pow(2, this.zoomLevel - zoomEvent.level);
        this.y = this.y / Math.pow(2, this.zoomLevel - zoomEvent.level);

        if (zoomEvent.level - this.zoomLevel > 0) {
            this.x -=  Math.floor(this.width / 2);
            this.y -=  this.height;
        }

        this.zoomLevel = zoomEvent.level;
        this.position();
    },

    /**
     * Suppression du marqueur
     * (!! ne supprime rien dans la base de données !!)
     */
    del: function() {
        this.element.parentNode.removeChild(this.element);
    }
}

