﻿"use strict";

if (!Poseidon.Controls) {
    Poseidon.Controls = {};
}

Poseidon.Controls.MeasureDistance = Ext.extend(Ext.Window, {
    //height: 225,
    autoHeight: true,
    width: 250,
    resizable: false,
    closable: true,
    closeAction: 'hide',
    resetText: 'Nulstil',
    measureLabel: 'Opmåling',
    measuring: false,
    showLineLengths: false,
    numberOfDecimalsMeters: 0,
    numberOfDecimalsKiloMeters: 3,
    useGeodesic: false,

    initComponent: function () {
        var callbacks;

        if (this.showLineLengths) {
            this.layer = new OpenLayers.Layer.Vector('', {
                displayInLayerSwitcher: false
            });

            this.layer.addOptions({
                visibility: false,
                displayInLayerSwitcher: false
            });
            callbacks = {
                modify: this.drawLineLength
            }
            this.mouseMovements = 0;
        }

        var measureControl = new OpenLayers.Control.Measure(OpenLayers.Handler.Path, {
            persist: true,
            geodesic: this.useGeodesic,
            handlerOptions: {
                layerOptions: {
                    styleMap: this.styleMap
                }
            },
            layer: this.showLineLengths ? this.layer : null,
            textNodes: [],
            callbacks: callbacks
        });

        var measureItem = new Ext.BoxComponent({
            fieldLabel: this.measureLabel,
            anchor: '100%',
            style: 'color: #000000; text-align: right; border: 1px solid #000000; background-color: #f0f0f0; padding-right: 2px;',
            html: '&nbsp;'
        });

        this.controls = {
            measureControl: measureControl,
            measureItem: measureItem
        }

        this.items = [
        {
            xtype: 'container',
            layout: 'form',
            style: 'padding: 5px;',
            items:
            [
                {
                    xtype: 'box',
                    html: this.description + '<br><br>',
                    anchor: '100%'
                }, {
                    xtype: 'box',
                    html: '<hr>',
                    anchor: '100%'
                },
                measureItem
            ]
        }];

        this.buttons = [
        {
            text: this.resetText,
            handler: function () {
                this.controls.measureItem.update('&nbsp;');
                this.controls.measureControl.cancel();
                this.disable();
                this.enable();
            },
            scope: this
        }];

        Poseidon.Controls.MeasureDistance.superclass.initComponent.apply(this, arguments);
    },

    // Function to handle the addition of a point during measurements.
    addPoint: function (event) {
        // If this is the first point, remember that a new measuring is performed.
        if (this.showLineLengths && !this.measuring) {
            // Make a local reference to the text nodes.
            var textNodes = this.controls.measureControl.textNodes;
            // Clear the textNode reference.
            this.controls.measureControl.textNodes = [];
            this.layer.destroyFeatures();

            map.setLayerZIndex(this.layer, map.layers.length);
            this.measuring = true;

            // Destroy all the nodes properly.
            //while (textNodes.length > 0) {
            //textNodes.pop().destroy();
            //}
        }

        var units = event.units,
            order = event.order,
            measure = event.measure,
            currentNumberOfDecimals = 0,
            measurement = "";

        // Set the requested number of decimals.
        currentNumberOfDecimals = units === 'm' ? this.numberOfDecimalsMeters : this.numberOfDecimalsKiloMeters;

        if (order === 1) {
            measurement += dot2comma(measure.toFixed(currentNumberOfDecimals)) + " " + units;
        } else {
            measurement += dot2comma(measure.toFixed(currentNumberOfDecimals)) + " " + units + "<sup>2</sup>";
        }

        this.controls.measureItem.update(measurement);
    },

    // Function to handle the ending of a measurement.
    doneMeasuring: function (event) {
        // Finish the last point.
        this.addPoint(event);

        // Remember that this was the last point of a measurement.
        if (this.showLineLengths) {
            this.measuring = false;
            this.mouseMovements = 0;
        }
    },

    drawLineLength: function (point, line) {
        if (this.mouseMovements++ < 5) {
            return;
        }
        var numberOfLines = line.geometry.components.length;
        if (numberOfLines < 2) {
            return;
        }
        var point = line.geometry.components[numberOfLines - 2];
        var startPoint = new OpenLayers.Geometry.Point(point.x, point.y);

        point = line.geometry.components[numberOfLines - 1];
        var endPoint = new OpenLayers.Geometry.Point(point.x, point.y);
        var lineSegment = new OpenLayers.Geometry.LineString([startPoint, endPoint]);
        var lineLength = this.getBestLength(lineSegment);
        if (!lineLength[0]) {
            return;
        }
        //var totalLength = this.getBestLength(line.geometry);
        // Use the user-specified precision.
        var currentNumberOfDecimals = lineLength[1] === 'm' ? this.numberOfDecimalsMeters : this.numberOfDecimalsKiloMeters;
        var labelString = '';
        labelString = dot2comma(lineLength[0].toFixed(currentNumberOfDecimals)) + ' ' + lineLength[1];
        var textNode = this.textNodes[numberOfLines - 2] || null;
        if (textNode && !textNode.layer) {
            this.textNodes.pop().destroy();
            textNode = null;
        }
        if (!textNode) {
            var lineCentroid = lineSegment.getCentroid();
            textNode = new OpenLayers.Feature.Vector(
                new OpenLayers.Geometry.Point(lineCentroid.x, lineCentroid.y), {}, {
                    label: '',
                    fontColor: '#FF0000',
                    fontSize: '14px',
                    fontFamily: 'Arial',
                    fontWeight: 'bold',
                    labelAlign: 'cm'
                }
            );
            this.textNodes.push(textNode);
            this.layer.addFeatures([textNode]);
        }
        textNode.geometry.x = (startPoint.x + endPoint.x) / 2;
        textNode.geometry.y = (startPoint.y + endPoint.y) / 2;
        textNode.style.label = labelString;
        textNode.layer.drawFeature(textNode);
        this.layer.drawFeature(textNode);
        //        this.events.triggerEvent('measuredynamic', {
        //            measure: lineLength[0],
        //            total: totalLength[0],
        //            units: lineLength[1],
        //            order: 1,
        //            geometry: lineSegment
        //        });        
    },

    enable: function () {
        this.controls.measureControl.events.register('measure', this, this.doneMeasuring);
        this.controls.measureControl.events.register('measurepartial', this, this.addPoint);

        if (this.showLineLengths) {
            // If the layer has not been added to the map, do it now. It has to be done after initialising.
            if (!this.layer.map) {
                map.addLayer(this.layer);
            }

            this.layer.setVisibility(true);
        }
    },

    disable: function () {
        if (this.controls.measureControl) {
            this.controls.measureControl.events.unregister('measure', this, this.doneMeasuring);
            this.controls.measureControl.events.unregister('measurepartial', this, this.addPoint);

            if (this.showLineLengths) {
                this.layer.setVisibility(false);
                this.layer.destroyFeatures();
            }
        }
    },

    hide: function () {
        // Call parent hide.
        Poseidon.Controls.MeasureDistance.superclass.hide.call(this);

        // Reset the measurement.
        this.controls.measureItem.update('&nbsp;');

        // Toggle toolbar.
        var button = Ext.getCmp(this.toolBarItem);
        if (button.pressed === true) {
            button.toggle();
        }
    }

    //    show: function () {
    //         // Call parent show.
    //        Poseidon.Controls.MeasureDistance.superclass.show.call(this);
    //        
    //        this.measureDistanceControl.activate();
    //    }
});
