DNow.CustomRadiiDialog = Class.create(aw.ui.Dialog, {

    _addressField: null,
    _nameField: null,
    _latitudeField: null,
    _longitudeField: null,

    _rangeField: null,
    _unitsField: null,

    _editPointButton: null,
    _removePointButton: null,
    _removeAllPointsButton: null,

    _grid: null,

    _points: [],

    initialize: function (properties, events) {
        this._points = [];

        this.inheritCSS = true;

        Object.extend(properties, {
            'title': 'Create Custom Locations'
        });

        aw.ui.Dialog.prototype.initialize.apply(this, arguments);

        if (this.componentBus) {
            this.componentBus.getComponentReferences('aw.GeographyManager', function (components) {
                if ((components) && (components.length > 0)) {
                    var gm = components[0];

                    this._onActiveGeographyChanged_fx = this._onActiveGeographyChanged.bind(this);
                    this._onGeographySettingsReceived_fx = this._onGeographySettingsReceived.bind(this);

                    gm.registerEvent('onactivegeographychanged', this._onActiveGeographyChanged_fx);
                    gm.registerEvent('ongeographysettingsreceived', this._onGeographySettingsReceived_fx);

                    if (gm.geographySettings)
                        this._onGeographySettingsReceived(gm.geographySettings);

                    if (gm.activeGeography)
                        this._onActiveGeographyChanged(gm.activeGeography);
                }
            }.bind(this));
        }
    },

    _addPoint: function (name, lat, lon) {
        this._points.push({ 'key': this.getId(), 'name': name, 'latitude': lat, 'longitude': lon });

        if (this._grid)
            this._grid.loadData(this._points);
    },

    _clearPoints: function () {
        this._points = [];
        if (this._grid)
            this._grid.loadData(this._points);
    },

    draw: function () {
        aw.ui.Dialog.prototype.draw.apply(this);

        var contents = this.canvas.down('div.contents');
        if (contents) {
            contents.update(this._local_templates['ui']);

            var addressField = contents.down('div.addressField');
            var nameField = contents.down('div.nameField');
            var latitudeField = contents.down('div.latitudeField');
            var longitudeField = contents.down('div.longitudeField');
            var addpointButton = contents.down('div.addpointButton');

            this._addressField = new aw.ui.Control.TextBox({ 'container': addressField, 'name': 'address', 'cssClass': 'addressInput' }, { 'enter': this._geocodeAddress.bind(this) });
            this._nameField = new aw.ui.Control.TextBox({ 'container': nameField, 'name': 'name', 'label': 'Name:' }, { 'enter': this._onAddPointClick.bind(this) });
            this._latitudeField = new aw.ui.Control.TextBox({ 'container': latitudeField, 'name': 'latitude', 'label': 'Latitude:' }, { 'enter': this._onAddPointClick.bind(this) });
            this._longitudeField = new aw.ui.Control.TextBox({ 'container': longitudeField, 'name': 'longitude', 'label': 'Longitude:' }, { 'enter': this._onAddPointClick.bind(this) });

            new aw.ui.Control.Button({ 'container': addpointButton, 'label': 'Add Point' }, { 'click': this._onAddPointClick.bind(this) });

            var mapButton = contents.down('div.mapButton');
            new aw.ui.Control.Button({ 'container': mapButton, 'label': 'Go to Map' }, { 'click': this._onGoToMapClick.bind(this) });

            var summary = contents.down('div.summary');

            this._grid = new aw.ui.Grid({
                'columns': [
                    { 'index': 'name', 'label': 'Name', 'sorted': true, 'sortDirection': 'asc' },
                    { 'index': 'latitude', 'label': 'Latitude' },
                    { 'index': 'longitude', 'label': 'Longitude'}]
            }, {
                'onselectionchanged': this._onPointSelectionChanged.bind(this)
            });

            this._editPointButton = new aw.ui.Control.Button({ 'label': 'Edit Point', 'disabled': true }, { 'click': this._onEditPointClick.bind(this) });
            this._removePointButton = new aw.ui.Control.Button({ 'label': 'Remove Point(s)', 'disabled': true }, { 'click': this._onRemovePointClick.bind(this) });
            this._removeAllPointsButton = new aw.ui.Control.Button({ 'label': 'Remove All Points' }, { 'click': this._onRemoveAllPointsClick.bind(this) });

            this._rangesInput = new aw.ui.Control.TextBox({ 'label': 'Ranges:', 'value': '1,3,5' });
            this._unitsSelect = new aw.ui.Control.DropDown({ 'label': 'Units:' });

            new aw.ui.Panel({
                'container': summary,
                'title': 'Current Points',
                'items': [
                    new aw.ui.Toolbar({
                        'height': 30,
                        'region': 'top',
                        'items': [
                            new aw.ui.Toolbar.Row({
                                'items': [
                                    this._editPointButton,
                                    this._removePointButton,
                                    this._removeAllPointsButton
                                ]
                            })
                        ]
                    }),
                    new aw.ui.Toolbar({
                        'height': 30,
                        'region': 'bottom',
                        'items': [
                            new aw.ui.Toolbar.Row({
                                'items': [
                                    this._rangesInput,
                                    this._unitsSelect
                                ]
                            })
                        ]
                    }),
                    this._grid
                ]
            });
        }

        this._renderButton('OK', this._onCreateCustomRadiiClick.bind(this));
        this._renderButton('Cancel', this.close.bind(this));

        return this.canvas;
    },

    _geocodeAddress: function () {
        if (!this.componentBus)
            throw "Could not locate a valid <aw.ComponentBus> class reference.";

        var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
        if ((gm) && (gm.length > 0)) {
            gm = gm[0];
            gm.search(this._addressField.value, this._onSearchReceived.bind(this));
        }
    },

    _onAddPointClick: function () {
        if (this._addressField.value !== '') {
            this._geocodeAddress();
            return;
        }

        var name = this._nameField.value;
        var lat = this._latitudeField.value;
        var lon = this._longitudeField.value;

        if ((!name) || (name === '') || (!lat) || (lat === '') || (!lon) || (lon === '')) {
            new aw.ui.Dialog.Error({ 'title': 'Error', 'content': 'You must enter the name, latitude, and longitude for the point you would like to add.' });
            return;
        } else if ((lon < -180.0) || (lon > 180.0) || (lat < -90.0) || (lat > 90.0)) {
            new aw.ui.Dialog.Error({ 'title': 'Error', 'content': 'Invalid latitude and/or longitude coordinates specified.' });
            return;
        }

        this._nameField.setValue('');
        this._latitudeField.setValue('');
        this._longitudeField.setValue('');

        this._addPoint(name, lat, lon);
    },

    _onCreateCustomRadiiClick: function () {
        var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
        if ((gm) && (gm.length > 0))
            gm = gm[0];
        else
            return;

        var validateRanges = gm.validateRadii(this._rangesInput.getValue(), this._unitsSelect.getValue());
        if (validateRanges.isGood !== true) {
            new aw.ui.Dialog.Error({ 'title': 'Error!', 'content': validateRanges.message });
            return;
        }

        geoCollection = new aw.GeographyCollection();

        var point = null, range = null;
        for (var i = 0; point = this._points[i]; i++) {
            for (var j = 0; range = validateRanges.ranges[j]; j++) {
                if (this._unitsSelect.getValue() == 'DT|Minutes')
                    geoCollection.addGeography(new aw.Geography.Drivetime(null, point.name, point.name, range, point.longitude, point.latitude, 'Minutes'));
                //RALLY DE103 - Account for multiple speed profiles
                else if (this._unitsSelect.getValue().indexOf('DT|Minutes|') != -1)
                    geoCollection.addGeography(new aw.Geography.Drivetime(null, point.name, point.name, range, point.longitude, point.latitude, 'Minutes', this._unitsSelect.getValue().split("|")[2]));
                //END RALLY DE103------------------------------
                else
                    geoCollection.addGeography(new aw.Geography.Radius(null, point.name, point.name, range, point.longitude, point.latitude, this._unitsSelect.getValue()));
            }
        }

        geoCollection.generateLabel();

        this.triggerEvent('onpointscreated', geoCollection);
        this.close();
    },

    _onEditPointClick: function (control) {
        if (!this._grid)
            return;

        var selectedRecords = this._grid.getSelectedRecords();
        if ((selectedRecords) && (selectedRecords.length > 0)) {
            this._removePointByKey(selectedRecords[0].key);

            this._nameField.setValue(selectedRecords[0].name);
            this._latitudeField.setValue(selectedRecords[0].latitude);
            this._longitudeField.setValue(selectedRecords[0].longitude);
        }
    },

    _onGeographySettingsReceived: function (settings) {
        if ((this._unitsSelect) && (settings)) {
            var units = [
                { 'value': 'Miles', 'label': 'Miles' },
                { 'value': 'Kilometers', 'label': 'Kilometers' }
            ];


            if (settings.enableDrivetimeGeography === true) {
                //RALLY DE103 - Account for multiple speed profiles
                var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
                if ((gm) && (gm.length > 0)) {
                    gm = gm[0];
                    gds = gm.guzzlerDataset;
                    if (gds.speeds != null) {
                        for (i = 0; i < gds.speeds.length; i++)
                            units.push({ 'value': "DT|Minutes|" + gds.key + "." + gds.speeds[i], 'label': "Minutes (" + gds.speeds[i] + ")" });
                    }
                    ///end RALLY DE103
                    else
                        units.push({ 'value': 'DT|Minutes', 'label': 'Minutes (Drivetime)' });
                }
            }

            this._unitsSelect.clear();
            this._unitsSelect.addOptions(units);

            var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
            if ((gm) && (gm.length > 0)) {
                gm = gm[0];
                if (gm.activeGeography)
                    this._loadGeographyInfo(gm.activeGeography);
            }
        }
    },

    _onPointSelectionChanged: function (selection) {
        this._editPointButton.disable();
        this._removePointButton.disable();

        if ((selection) && (selection.length > 0)) {
            this._removePointButton.enable();
            if (selection.length == 1)
                this._editPointButton.enable();
        }
    },

    _onRemoveAllPointsClick: function (control) {
        this._clearPoints();
    },

    _onRemovePointClick: function (control) {
        var grid = this._grid;
        if (!grid)
            return;

        var selectedRecords = grid.getSelectedRecords();
        if ((selectedRecords) && (selectedRecords.length > 0)) {
            var record = null;
            for (var i = 0; record = selectedRecords[i]; i++) {
                this._removePointByKey(record.key);
            }
        }
    },

    _loadGeographyInfo: function (geoCollection) {
        if ((!geoCollection) || (!geoCollection.geos) || (!geoCollection.geos.length > 0) || (!this._unitsSelect))
            return;

        if ((this._rangesInput) && (this._unitsSelect)) {
            var geoTypes = geoCollection.getGeographyTypes();
            if ((geoTypes.length > 1) || ((geoTypes[0] != 'aw.Geography.Radius') && (geoTypes[0] != 'aw.Geography.Drivetime')))
                return;

            var radiiInfo = geoCollection.getRadiiInfo();
            if (radiiInfo) {
                this._rangesInput.setValue(radiiInfo.sizes);
                this._unitsSelect.selectByValue(radiiInfo.units);
            }
        }
    },

    _onActiveGeographyChanged: function (geoCollection) {
        this._loadGeographyInfo(geoCollection);
    },

    _onGoToMapClick: function () {
        var mv = this.componentBus.getComponentReferences('DNow.MapViewer');
        if ((mv) && (mv.length > 0)) {
            mv[0]._map.pickPoint(this._onMapPointClick.bind(this));
            mv[0].show();
            this.hide();

            new aw.ui.Dialog.Alert({ 'title': 'Pick Point From Map', 'content': 'Click a location on the map to add it to your list of points.' });
        }
    },

    _onMapPointClick: function (point, name) {
        if ((!name) || (name === '')) {
            new aw.ui.Dialog.Prompt({ 'title': 'Enter Point Name', 'content': 'Please enter a name for the point created at ' + point.lat + ', ' + point.lon + '.' }, { 'onsubmit': this._onMapPointClick.bind(this, point) });
        } else {
            this._addPoint(name, point.lat, point.lon);
            this.show();
        }
    },

    _onSearchReceived: function (results) {
        for (var i = 0; result = results[i]; i++) {
            if ((result.TypeGeo == 'Street') || (result.TypeGeo == 'Address')) {
                this._addPoint(result.Name, result.Lat, result.Lon);
                this._addressField.setValue('');
                return;
            }
        }

        new aw.ui.Dialog.Error({ 'title': 'Error', 'content': 'No matches were found for your search.' });
    },

    _removePointByKey: function (key) {
        if ((!key) || (!this._points) || (!this._points.length > 0))
            return;

        var points = [], point = null, bFound = false;
        for (var i = 0; point = this._points[i]; i++) {
            if (point.key != key)
                points.push(point);
            else
                bFound = true;
        }

        if (bFound === true) {
            this._points = points;
            if (this._grid)
                this._grid.loadData(this._points);
        }
    },

    _local_templates: {
        'ui': '<div class="location">' +
                '<h2>Enter a Post Code...</h2>' +
                '<div class="addressField"></div>' +
                '<div class="split horizontal"></div>' +
                '<h2>Or Enter a Name and Coordinates...</h2>' +
                '<div class="nameField"></div>' +
                '<div class="latitudeField"></div><div class="longitudeField"></div>' +
                '<div class="addpointButton"></div>' +
            '</div>' +
            '<div class="map">' +
                '<h2>Pick from Map...</h2>' +
                '<span>Click "Go to Map" to pick your point from the map.</span>' +
                '<div class="mapButton"></div>' +
            '</div>' +
            '<div class="summary"></div>'
    },

    EVENTS: ['onpointscreated'],

    CLASS_NAME: 'DNow.CustomRadiiDialog'
});
