/**
 * @class
 * 
 * @requires OpenLayers/Layer/Markers.js
 */

Daedalus.Flags = OpenLayers.Class.create();
Daedalus.Flags.prototype = 
    OpenLayers.Class.inherit( Daedalus.Base, OpenLayers.Layer.Markers, {

        /** store url of text file - this should be specified in the 
         *   "options" hashtable
        * @type str */
        location: null,

        /** @type Object(OpenLayers.Feature) */
        flags: null,

        /** @type OpenLayers.Feature */
        // selectedFeature: null,
        
        /** @type int */
        version: 0,
        
        /** @type int */
        period: 0,

        /**
        * @constructor
        *
        * @param {String} name
        * @param {String} location
        * @param {Object} options Hashtable of extra options to tag onto the layer
        */
        initialize: function(name, options) {
            OpenLayers.Layer.Markers.prototype.initialize.apply(this, arguments);
            // Should be able to pass this in.
            this.period = 30000;
            this.clearFlags();
            this.fetchUpdate();
        },

       /**
         * 
         */
        destroy: function() {
            this.clearFlags();
            OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments);
        },

        /**
         * @param {OpenLayers.Bounds} bound
         * @param {Boolean} zoomChanged tells when zoom has changed, as layers 
         *                   have to do some init work in that case.
         * @param {Boolean} dragging
         */
        moveTo: function(bounds, zoomChanged, dragging) {
            OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments);
        
            //this.fetchUpdate();
            //         
            // var mon = $('monitor');
            //         
            // var centre = bounds.getCenterLonLat();
            //         
            // var text = "bounds: " + bounds + "<br />\n" 
            //         + "centre: " + centre + "<br />\n"
            //         + "zoomChanged: " + zoomChanged + "<br />\n"
            //         + "dragging: " + dragging + "<br />\n"
            //         + "location: " + this.location;
            //         
            // mon.innerHTML = text;
        
        },

        fetchUpdate: function() {
            if (this.location != null) {
                OpenLayers.loadURL(
                    this.location, 
                    'version=' + this.version,
                    this, 
                    this.parseUpdate,
                    this.failUpdate
                );
            }
        },

        parseJSON: function(text) {
            try {
                return eval('(' + text + ')');
            } catch (e) {
                // Do nothing
            }
            
            return null;
        },

        /**
         * @param {Event} evt
         */
        markerClick: function(evt) {
            var flag = this.getFeatureFromEvent(evt);
            if (flag) {
                this.signal('markerClick', flag);
            }
            OpenLayers.Event.stop(evt);
        },

        /* Enabled flags to be handled by Handler/Feature */
        getFeatureFromEvent: function(evt) {
            var node = OpenLayers.Event.element(evt);

            /** TODO: We need a better way to do this. */
            for (var id in this.flags) {
                var flag = this.flags[id];
                if (flag.icon.imageDiv.id == node.id) {
                    return flag;
                }
                if (flag.icon.imageDiv.firstChild.id == node.id) {
                    return flag;
                }
            }
            return null;
        },

        createFlag: function(location, data) {
            var flag = new Daedalus.Flag(location, data);
            
            this.flags[data.id] = flag;
            return flag;
        },

        updateFlag: function(spec) {
            this.deleteFlag(spec.id);

            var icon = this.icons[spec.icontype_id];
            if (!icon) {
                // alert("icon " + spec.icon + " not known");
                return;
            }
            
            var location = new OpenLayers.LonLat( spec.e, spec.n );
            
            var data = { 
                icon: new OpenLayers.Icon(icon.url, icon.size, null),
                id:   spec.id,
                type: spec.icontype_id
            };

            var flag = this.createFlag(location, data);
            if (spec.comment) {
                flag.setComment(spec.comment);
            }
            this.flags[data.id] = flag;

            flag.events.register('click', this, this.markerClick);
            this.addMarker(flag);

            return flag;
        },

        deleteFlag: function(id) {
            if (this.flags[id]) {
                this.removeMarker(this.flags[id]);
                this.flags[id].destroy();
                delete this.flags[id];
            }
        },

        armTimer: function() {
            // var self = this;
            // setTimeout(function() { self.fetchUpdate() }, this.period);
        },

        parseUpdate: function(ajaxRequest) {
            var data = this.parseJSON(ajaxRequest.responseText);
            if (data) {
                // Data is a delta
                if (data.del) {
                    for (var i = 0; i < data.del.length; i++) {
                        this.deleteFlag(data.del[i]);
                    }
                }
                
                if (data.upd) {
                    for (var i = 0; i < data.upd.length; i++) {
                        this.updateFlag(data.upd[i]);
                    }
                }
                
                this.version = data.version;
            }
            
            this.armTimer();
        },
        
        failUpdate: function(ajaxRequest) {
            this.armTimer();
        },
    
        /**
         * 
         */
        clearFlags: function() {
            if (this.flags) {
                for (var f in this.flags) {
                    this.flags[f].destroy();
                    this.flags[f] = null;
                }
            }
            this.flags = new Object();
        },
        
        getData: function() {
            // Need to call new Object instead of {} so toJSON
            // works correctly
            var data = new Object;
            for (var f in this.flags) {
                data[f] = this.flags[f].getData();
            }
            return data;
        },
        
        loadData: function(data) {
            var d = data.evalJSON();
            for (var i in d) {
                this.updateFlag(d[i]);
            }
        },
    
        /** @final @type String */
        CLASS_NAME: "Daedalus.Flags"
    }
);
     
    
