DNow.QueryViewer = Class.create(aw.ui.Panel, {

    _datasetDropDown: null,
    _fieldTree: null,
    _querySummaryTree: null,

    _activeFilter: null,

    _rangeBeginComboBox: null,
    _rangeEndComboBox: null,

    _deleteFilterButton: null,

    _savedFilters: [],
    _listDatasets: [],

    initialize: function (properties, events) {
        this._datasetDropDown = null;
        this._fieldTree = null;
        this._querySummaryTree = null;

        this._activeFilter = null;

        this._rangeBeginComboBox = null;
        this._rangeEndComboBox = null;

        this._deleteFilterButton = null;

        this._savedFilters = [];
        this._listDatasets = [];

        this.inheritCSS = true;

        aw.ui.Panel.prototype.initialize.apply(this, arguments);

        if (this.componentBus) {
            this.componentBus.getComponentReferences('aw.QueryManager', function (components) {
                if ((components) && (components.length > 0)) {
                    var qm = components[0];
                    qm.registerEvent('onquerydatasetschanged', this._onQueryDatasetsChanged.bind(this));
                    qm.registerEvent('onquerydatasetchanged', this._onQueryDatasetChanged.bind(this));
                    qm.registerEvent('onquerycountreceived', this._onQueryCountReceived.bind(this));
                    qm.registerEvent('ondatasetmetadatareceived', this._onQueryDatasetMetadataReceived.bind(this));
                    qm.registerEvent('onactivequerychanged', this._onActiveQueryChanged.bind(this));
                    qm.registerEvent('onquerysaved', this._onQuerySaved.bind(this));

                    var datasets = qm.getAllQueryDatasets();
                    if ((datasets) && (datasets.length > 0))
                        this._onQueryDatasetsChanged(datasets);

                    if (qm.activeQueryDataset)
                        this._onQueryDatasetChanged(qm.activeQueryDataset);

                }
            } .bind(this));

            this.componentBus.getComponentReferences('aw.GeographyManager', function (components) {
                if ((components) && (components.length > 0)) {
                    var gm = components[0];
                    gm.registerEvent('onactivegeographychanged', this._onActiveGeographyChanged.bind(this));

                    if (gm.activeGeography)
                        this._onActiveGeographyChanged(gm.activeGeography);
                }
            } .bind(this));

            this.componentBus.getComponentReferences('aw.UserDataManager', function (components) {
                if ((components) && (components.length > 0)) {
                    var udm = components[0];
                    udm.registerEvent('onactionexecuted', this._onUserDataActionExecuted.bind(this));
                }
            } .bind(this));
        }
    },

    draw: function () {
        aw.ui.Panel.prototype.draw.apply(this);

        this._datasetDropDown = new aw.ui.Control.DropDown({ 'label': 'Dataset: ', 'options': [{ 'value': '', 'label': 'Loading...'}] }, { 'change': this._onDatasetDropDownChanged.bind(this) });
        this._fieldTree = new aw.ui.Tree({ 'mode': 'single', 'accordion': true, 'cssClass': 'fieldTree' }, { 'onselectionchanged': this._onFieldTreeSelectionChanged.bind(this) });
        this._querySummaryTree = new aw.ui.Tree({ 'mode': 'single' }, { 'onselectionchanged': this._onSummaryTreeSelectionChanged.bind(this) });

        this._queryNameLabel = new aw.ui.Control.Label({ 'label': 'Query Name: ', 'value': 'Temporary Query' });
        this._queryCountLabel = new aw.ui.Control.Label({ 'label': 'Record Count (within current geography): ', 'value': '0' });

        this._deleteFilterButton = new aw.ui.Control.Button({ 'label': 'Delete Selected Item', 'align': 'right', 'disabled': true }, { 'click': this._onDeleteFilterClick.bind(this) });

        this._activeFilterPanel = new aw.ui.Panel({
            'title': 'No Field Selected',
            'minWidth': 300,
            'width': 600,
            'items': [
                new aw.ui.HTML({
                    'html': '<div class="filterSelection">' +
                            '<select name="filterType" id="filterType"></select>' +
                            '<div class="filterValue" style="display: none;"></div>' +
                        '</div>' +
                        '<div class="filterList" style="display: none;"></div>' +
						'<div class="filterTree" style="display: none;"></div>' +
                        '<div class="filterOptions">' +
                            '<div class="inverse"><input type="checkbox" name="filterInverse" id="filterInverse" /> Inverse (Not)</div>' +
                            '<div class="clear"></div>' +
                        '</div>'
                })
            ]
        });

        this.add(
            new aw.ui.Toolbar({
                'region': 'top',
                'height': 100,
                'cssClass': 'DNow_Toolbar',
                'items': [
                   new aw.ui.Toolbar.Group({
                       'label': 'Geography Selection',
                       'cssClass': 'geoselection',
                       'items': [
                            new DNow.GeographyBar({
                                'componentBus': this.componentBus
                            })
                        ],
                       'helpCallback': this._onHelpClick.bind(this, 'Geography Selection')
                   }),
                    new aw.ui.Toolbar.Group({
                        'label': 'Query Options',
                        'items': [
                            new aw.ui.Toolbar.Column({
                                'items': [
                                    this._datasetDropDown,
                                    new aw.ui.Toolbar.Row({
                                        'items': [
                                            new aw.ui.Control.Button({ 'label': 'Open' }, { 'click': this._onOpenQueryClick.bind(this) }),
                                            new aw.ui.Control.Button({ 'label': 'Save' }, { 'click': this._onSaveQueryClick.bind(this) })
                                        ]
                                    })
                                ]
                            })
                        ],
                        'helpCallback': this._onHelpClick.bind(this, 'Query:Query Options')
                    })
                ]
            }));

        this.add(
            new aw.ui.Panel.Splitter({
                'titleVisibility': false,
                'orientation': 'horizontal',
                'items': [
                    new aw.ui.Panel({
                        'title': 'Fields',
                        'minWidth': 200,
                        'width': 200,
                        'items': [this._fieldTree]
                    }),
                    this._activeFilterPanel,
                    new aw.ui.Panel({
                        'title': 'Query Summary',
                        'minWidth': 300,
                        'width': 300,
                        'cssClass': 'querySummary',
                        'items': [
                            new aw.ui.Toolbar({
                                'height': 55,
                                'region': 'top',
                                'items': [
                                    new aw.ui.Toolbar.Column({
                                        'items': [
                                            this._queryNameLabel,
                                            this._queryCountLabel
                                        ]
                                    })
                                ]
                            }),
                            this._querySummaryTree,
                            new aw.ui.Toolbar({
                                'height': 30,
                                'region': 'bottom',
                                'items': [
                                    new aw.ui.Toolbar.Row({
                                        'items': [this._deleteFilterButton]
                                    })
                                ]
                            })
                        ]
                    })
                ]
            }));

        this._filterTypeSelect = this._activeFilterPanel.canvas.down('select[id="filterType"]');
        aw.EventManager.register(this._filterTypeSelect, 'change', this._onFilterTypeSelectChanged.bind(this));

        this._filterValueContainer = this._activeFilterPanel.canvas.down('div.filterValue');
        this._filterListContainer = this._activeFilterPanel.canvas.down('div.filterList');
        this._filterTreeContainer = this._activeFilterPanel.canvas.down('div.filterTree');
        this._filterInverseCheck = this._activeFilterPanel.canvas.down('input[id="filterInverse"]');
        aw.EventManager.register(this._filterInverseCheck, 'click', this._onFilterInverseCheckClick.bind(this));

        var clearContainer = this._activeFilterPanel.canvas.down('div.clear');
        if (clearContainer) {
            clearContainer.update('');
            new aw.ui.Control.Button({ 'label': 'Clear', 'container': clearContainer }, { 'click': this._onFilterClearClick.bind(this) });
        }

        return this.canvas;
    },

    _buildQueryLayer: function (query, dataset) {
        var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
        if ((!gm) || (!gm.length > 0))
            return;

        var geoCollection = gm[0].activeGeography;
        if (!geoCollection)
            return;

        var geoDefinition = geoCollection.getGeographyDefinition();

        var map = this.componentBus.getComponentReferences('aw.ui.Map');
        if ((map) && (map.length > 0)) {
            map = map[0];

            var activeQueryLayer = map.getLayerByKey('activequery');
            if (activeQueryLayer) {
                activeQueryLayer.setDataset(dataset.key);
                activeQueryLayer.setGeoCollection(geoDefinition);
                activeQueryLayer.setQuery(query);
            } else {
                map.addLayer(new aw.ui.Map.Layer.Point.Query({ 'key': 'activequery', 'label': 'Active Query', 'labelTemplate': 'ActiveQueryLabel', 'labelControllable': true, 'options': false, 'dataset': dataset.key, 'query': query, 'geoCollection': geoDefinition, 'visible': true, 'drawPriority': 6.1, 'parameters': { 'fillc': 'ff0000'} }));
            }
        }
    },

    _buildReportQuery: function (query, dataset) {
        /*
        var rm = this.componentBus.getComponentReferences( 'aw.ReportManager' );
        if ((rm) && (rm.length > 0)) {
        rm = rm[0];

        rm.removeReports( rm.getReportsBy( { 'type': 'Calgary', 'format': 'List', 'name': 'Temporary List Report' } ), false );
        rm.addReport( { 'format': 'List', 'name': 'Temporary List Report', 'type': 'Calgary', 'listOnly': false, 'variant': dataset.key, 'query': query.serialize( ) } );

        if (this.isVisible( ) === true) {
        var temporaryListReport = rm.getReportsBy( {'type': 'Calgary', 'format': 'List', 'name': 'Temporary List Report' } );
        if ((temporaryListReport) && (temporaryListReport.length > 0))
        rm.setActiveReport( temporaryListReport[0] );
        }
        }
        */
    },

    _executeQuery: function (geoCollection, dataset) {
        if ((!geoCollection) || (!dataset))
            return;

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0))
            qm = qm[0];
        else
            return;

        var query = null;
        if (qm.activeQuery) {
            query = qm.activeQuery;
            var spatialFilters = query.getItemsByClassName('aw.Query.Filter.Spatial');
            if ((spatialFilters) && (spatialFilters.length > 0)) {
                for (var i = 0; i < spatialFilters.length; i++) {
                    spatialFilters[i].geoCollection = geoCollection;
                }
            }
        } else {
            query = new aw.Query.Operator({ 'operator': 'And' });
            query.add(new aw.Query.Filter.Spatial({ 'geoCollection': geoCollection }));
        }

        qm.setActiveQuery(query);
    },

    _loadCalgaryReports: function () {
        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0))
            var dataset = qm[0].activeQueryDataset;
        else
            return;

        var udm = this.componentBus.getComponentReferences('aw.UserDataManager');
        if ((udm) && (udm.length > 0)) {
            udm = udm[0];

            udm.retrieveData('CalgaryListFilter', null, dataset.key, function (data) {
                var rm = this.componentBus.getComponentReferences('aw.ReportManager');
                if ((rm) && (rm.length > 0)) {
                    rm = rm[0];

                    if ((this._savedFilters) && (this._savedFilters.length > 0)) {
                        var filter = null;
                        for (var i = 0; filter = this._savedFilters[i]; i++) {
                            rm.removeReports(rm.getReportsBy({ 'type': 'Calgary', 'format': 'List', 'name': filter.name }), false);
                        }
                    }

                    this._savedFilters = [];
                    data.sortBy('name');
                    var reports = [];
                    for (var j = 0; filter = data[j]; j++) {
                        this._savedFilters.push(filter);
                        reports.push({ 'format': 'List', 'name': filter.name, 'type': 'Calgary', 'listOnly': false, 'variant': dataset.key, 'query': filter.query });
                    }

                    rm.addReports(reports);
                }
            } .bind(this));
        }
    },

    _loadQuery: function (parameters) {
        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((!qm) || (!qm.length > 0))
            return;

        var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
        if ((!gm) || (!gm.length > 0))
            return;

        qm = qm[0];
        gm = gm[0];

        if (this._loadQuery_fx) {
            qm.unregisterEvent('ondatasetmetadatareceived', this._loadQuery_fx);
            this._loadQuery_fx = null;
        }

        var query = qm.buildQueryObject(parameters.params.jsonQuery);
        query.add(new aw.Query.Filter.Spatial({ 'geoCollection': gm.activeGeography }));
        query.name = parameters.name;
        qm.setActiveQuery(query, parameters.name);

        if (this._queryNameLabel)
            this._queryNameLabel.setValue(parameters.name);

        this.show();
    },

    _onActiveGeographyChanged: function (geoCollection) {
        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0)) {
            qm = qm[0];

            if (qm.activeQueryDataset)
                this._executeQuery(geoCollection, qm.activeQueryDataset);
        }
    },

    _onActiveQueryChanged: function (query) {
        if (this._queryCountLabel)
            this._queryCountLabel.setValue('Loading...');

        if (this._queryNameLabel)
            this._queryNameLabel.setValue(((query) && (query.filterName)) ? query.filterName : 'Temporary Query');
    },

    _onDatasetDropDownChanged: function (control) {
        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0))
            qm[0].setActiveQueryDatasetByKey(control.getValue());
    },

    _onDeleteFilterClick: function (control) {
        if (!this._querySummaryTree)
            return;

        var selectedKeys = this._querySummaryTree.getSelectedKeys();
        if ((!selectedKeys) || (!selectedKeys.length > 0))
            return;

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0) && (qm[0].activeQuery))
            qm = qm[0];
        else
            return;

        var key = null, filter = null;
        for (var i = 0; key = selectedKeys[i]; i++) {
            filter = qm.activeQuery.getItemById(key);
            if ((filter) && (!filter.derivesFrom('aw.Query.Filter.Spatial'))) {
                qm.activeQuery.remove(filter);
                if (filter === this._activeFilter) {
                    this._activeFilter = null;
                    this._onFieldTreeSelectionChanged();
                }

                qm.setActiveQuery(qm.activeQuery);
            }
            filter = null;
        }
    },

    _onFieldTreeSelectionChanged: function (tree) {
        if (!this._fieldTree)
            return;

        var keys = this._fieldTree.getSelectedKeys();
        if ((!keys) || (keys.length !== 1))
            return;

        var key = keys[0];
        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0)) {
            qm = qm[0];

            qm.setActiveFieldIndexByName(key);
            var field = qm.activeFieldIndex;

            if (field) {
                this._activeFilterPanel.setTitle(field.shortName);
                this._setFilterTypeSelect(field);
            }
        }
    },

    _onFilterClearClick: function (control) {
        if (this._activeFilter) {
            var qm = this.componentBus.getComponentReferences('aw.QueryManager');
            if ((qm) && (qm.length > 0)) {
                qm = qm[0];

                if (qm.activeQuery) {
                    qm.activeQuery.remove(this._activeFilter);
                    this._activeFilter = null;
                    this._onFilterTypeSelectChanged();
                    qm.setActiveQuery(qm.activeQuery);
                }
            }
        }
    },

    _onFilterInverseCheckClick: function () {
        if (this._activeFilter) {
            var qm = this.componentBus.getComponentReferences('aw.QueryManager');
            if ((qm) && (qm.length > 0)) {
                qm = qm[0];

                this._activeFilter.inverse = this._filterInverseCheck.checked;
                qm.setActiveQuery(qm.activeQuery);
            }
        }
    },

    _onFilterListClick: function (e) {
        var ev = aw.EventManager.getEvent(e);
        var elt = ev.target;

        if (!elt)
            return;

        if ((elt.tagName) && (elt.tagName.toLowerCase() == 'input')) {
            var qm = this.componentBus.getComponentReferences('aw.QueryManager');
            if ((qm) && (qm.length > 0)) {
                qm = qm[0];
                if (!qm.activeFieldIndex)
                    return;
            } else {
                return;
            }

            if (!this._activeFilter) {
                this._activeFilter = new aw.Query.Filter.List({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
                qm.activeQuery.add(this._activeFilter);
            }

            if (elt.checked === true)
                this._activeFilter.addValue(elt.value);
            else
                this._activeFilter.removeValue(elt.value);

            this._activeFilter.inverse = this._filterInverseCheck.checked;

            qm.setActiveQuery(qm.activeQuery);
        }
    },

    _onFilterTypeSelectChanged: function () {
        var verb = this._filterTypeSelect.value;

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0)) {
            qm = qm[0];
            if (!qm.activeFieldIndex)
                return;
        } else {
            return;
        }

        var filterClassName = (qm.getFilterClassByVerb(verb)) ? qm.getFilterClassByVerb(verb).CLASS_NAME : null;

        if ((filterClassName) && (qm.activeQuery))
            this._activeFilter = qm.activeQuery.getFilterBy({ 'name': qm.activeFieldIndex.name, 'supports': qm.activeFieldIndex.type, 'CLASS_NAME': filterClassName });

        this._filterInverseCheck.checked = false;
        if (this._activeFilter)
            this._filterInverseCheck.checked = this._activeFilter.inverse;

        this._filterValueContainer.update('');
        this._filterListContainer.update('');
        this._filterTreeContainer.update('');

        this._filterValueContainer.hide();
        this._filterListContainer.hide();
        this._filterTreeContainer.hide();

        if (this._filterTreeTimeout) {
            clearTimeout(this._filterTreeTimeout);
            this._filterTreeTimeout = null;
        }

        var panel = verb;
        var options = [], option = null;
        if ((verb == 'is') || (verb == 'contains') || (verb == 'begins') || (verb == 'ends'))
            panel = 'value';

        if ((qm.activeFieldIndex.listTreeEnumerator) && (verb.match('is|list|listBegin'))) {
            this._filterTree = new aw.ui.Tree({
                'componentBus': this.componentBus,
                'container': this._filterTreeContainer,
                'mode': (verb == 'is') ? 'single' : 'multiple',
                'branchSelectable': (verb == 'is') ? false : true,
                'baseRequest': {
                    'cn': 'SRC.Web.Client.Handler.CalgaryHandler|' + qm.activeQueryDataset.variant,
                    'service': 'tree',
                    'sn': qm.activeFieldIndex.shortName,
                    'k': (this._activeFilter) ? (this._activeFilter.value || this._activeFilter.values) : null
                }
            });

            this._filterTreeTimeout = setTimeout(this._filterTree.registerEvent.bind(this._filterTree, 'onselectionchanged', this._onFilterTreeChanged.bind(this)), 150);

            this._filterTreeContainer.show();
            return;
        }

        if (panel == 'value') {
            new aw.ui.Control.TextBox({ 'changeDelay': 200, 'label': 'Value: ', 'container': this._filterValueContainer, 'value': ((this._activeFilter) ? this._activeFilter.value : null) }, { 'change': this._onFilterValueChanged.bind(this, panel) });
            this._filterValueContainer.show();
        } else if (panel == 'range') {
            if ((qm.activeFieldIndex.rangeValues) && (qm.activeFieldIndex.rangeValues.length > 0)) {
                for (var i = 0; option = qm.activeFieldIndex.rangeValues[i]; i++) {
                    options.push({ 'value': option.key, 'label': option.value });
                }
            }

            this._rangeBeginComboBox = new aw.ui.Control.ComboBox({ 'label': 'Between ', 'container': this._filterValueContainer, 'options': options, 'value': ((this._activeFilter) ? this._activeFilter.begins : null) }, { 'change': this._onFilterValueChanged.bind(this, panel) });
            this._rangeEndComboBox = new aw.ui.Control.ComboBox({ 'label': ' and ', 'container': this._filterValueContainer, 'options': options, 'value': ((this._activeFilter) ? this._activeFilter.ends : null) }, { 'change': this._onFilterValueChanged.bind(this, panel) });
            this._filterValueContainer.show();
        } else if (panel == 'null') {
            if (!this._activeFilter) {
                this._activeFilter = new aw.Query.Filter.Null({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
                this._activeFilter.inverse = this._filterInverseCheck.checked;
                qm.activeQuery.add(this._activeFilter);
                qm.setActiveQuery(qm.activeQuery);
            }
        } else if (panel == 'list') {
            if ((qm.activeFieldIndex.enumeratedValues) && (qm.activeFieldIndex.enumeratedValues.length > 0)) {
                var columns = 3;
                var rows = Math.ceil(qm.activeFieldIndex.enumeratedValues.length / columns);

                for (var r = 0; r < rows; r++) {
                    options.push('<tr>');
                    var c = 0;
                    for (var j = 0; j < qm.activeFieldIndex.enumeratedValues.length; j++) {
                        if (j % rows == r) {
                            option = qm.activeFieldIndex.enumeratedValues[j];
                            options.push('<td><input type="checkbox" key="fieldValue' + j + '" value="' + option.key + '" /> ' + option.value + '</td>');
                            c++;
                        }
                    }

                    while (c < columns) {
                        options.push('<td>&nbsp;</td>');
                        c++;
                    }

                    options.push('</tr>');
                }

                this._filterListContainer.update('<table cellspacing="0" cellpadding="0">' + options.join('') + '</table>');

                if ((this._activeFilter) && (this._activeFilter.values) && (this._activeFilter.values.length > 0)) {
                    var checkboxes = this._filterListContainer.select('input[value="' + this._activeFilter.values.join('"], input[value="') + '"]');
                    if ((checkboxes) && (checkboxes.length > 0)) {
                        for (var k = 0; k < checkboxes.length; k++) {
                            checkboxes[k].checked = true;
                        }
                    }
                }

                var filterListTable = this._filterListContainer.down('table');
                if (filterListTable)
                    aw.EventManager.register(filterListTable, 'click', this._onFilterListClick.bindAsEventListener(this));
                filterListTable = null;

                this._filterListContainer.show();
            }
        }
    },

    _onFilterTreeChanged: function (tree) {
        // This code will update the active filter value(s) based on the selected keys within the tree.
        // If the tree is a single-select (the verb is "is"), then we will likely do the same kind of processing we do in the _onFilterValueChanged method.
        // If the tree is a multi-select (the verb is "list"), then we will likely do the same kind of process we do in the _onFilterListClick method.
        if (!tree)
            return;

        var values = tree.getSelectedKeys();
        var filterVerb = this._filterTypeSelect.value;

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0)) {
            qm = qm[0];
            if (!qm.activeFieldIndex)
                return;
        } else {
            return;
        }

        if (!this._activeFilter) {
            if (filterVerb === 'is') {
                this._activeFilter = new aw.Query.Filter.Is({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            } else if (filterVerb === 'list') {
                this._activeFilter = new aw.Query.Filter.List({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            } else if (filterVerb === 'listBegin') {
                this._activeFilter = new aw.Query.Filter.ListBegin({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            } else {
                throw "Could not locate appropriate filter type.";
            }

            qm.activeQuery.add(this._activeFilter);
        }

        if ((!values) || (!values.length > 0)) {
            qm.activeQuery.remove(this._activeFilter);
            this._activeFilter = null;
        } else {
            if (filterVerb === 'is') {
                this._activeFilter.setValue(values[0]);
            } else if (filterVerb.match('list|listBegin')) {
                this._activeFilter.clear();
                for (var i = 0; i < values.length; i++) {
                    this._activeFilter.addValue(values[i]);
                }
            } else {
                throw "Could not locate appropriate filter type.";
            }
        }

        if (this._activeFilter)
            this._activeFilter.inverse = this._filterInverseCheck.checked;

        qm.setActiveQuery(qm.activeQuery);
    },

    _onFilterValueChanged: function (panel, control) {
        var filterVerb = this._filterTypeSelect.value;
        var value = control.getValue();

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0)) {
            qm = qm[0];
            if (!qm.activeFieldIndex)
                return;
        } else {
            return;
        }

        if (!this._activeFilter) {
            if (filterVerb == 'is')
                this._activeFilter = new aw.Query.Filter.Is({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            else if (filterVerb == 'begins')
                this._activeFilter = new aw.Query.Filter.Begins({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            else if (filterVerb == 'ends')
                this._activeFilter = new aw.Query.Filter.Ends({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            else if (filterVerb == 'contains')
                this._activeFilter = new aw.Query.Filter.Contains({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            else if (filterVerb == 'range')
                this._activeFilter = new aw.Query.Filter.Range({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            else if (filterVerb == 'list')
                this._activeFilter = new aw.Query.Filter.List({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            else if (filterVerb == 'listBegin')
                this._activeFilter = new aw.Query.Filter.ListBegin({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            else if (filterVerb == 'null')
                this._activeFilter = new aw.Query.Filter.Null({ 'name': qm.activeFieldIndex.name, 'label': qm.activeFieldIndex.shortName });
            else
                throw "Could not locate appropriate filter type.";

            qm.activeQuery.add(this._activeFilter);
        }

        if (filterVerb == 'range') {
            var _vals = [this._rangeBeginComboBox.getValue(), this._rangeEndComboBox.getValue()];
            this._activeFilter.setRangeBegin(Math.min(_vals[0], _vals[1]));
            this._activeFilter.setRangeEnd(Math.max(_vals[0], _vals[1]));
        } else if (filterVerb.match('is|begins|ends|contains')) {
            if ((!value) || (value === '')) {
                qm.activeQuery.remove(this._activeFilter);
                this._activeFilter = null;
            } else {
                this._activeFilter.setValue(value);
            }
        } else {
            throw "Could not locate appropriate filter type.";
        }

        if (this._activeFilter)
            this._activeFilter.inverse = this._filterInverseCheck.checked;

        qm.setActiveQuery(qm.activeQuery);
    },

    _onHelpClick: function (topic) {
        if (this.componentBus) {
            var help = this.componentBus.getComponentReferences('DNow.Help');
            if ((help) && (help.length > 0)) {
                help[0].loadTopicByTitle(topic);
                return;
            }
        }

        new DNow.Help({
            'componentBus': this.componentBus,
            'activeTopicKey': topic
        });
    },

    _onOpenQueryClick: function (control) {
        if (this.isSessionValidated() === true) {
            new DNow.SavedQueryDialog({ 'componentBus': this.componentBus });
        } else {
            new aw.ui.Dialog.Error({ 'title': 'Error', 'content': 'You must be logged in to access this functionality.' });
        }
    },

    _onQueryCountReceived: function (query) {
        if (!this._querySummaryTree)
            return;

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0)) {
            qm = qm[0];
            if (this._queryCountLabel)
                this._queryCountLabel.setValue(parseFloat(qm.activeQuery.count).addCommas());

            this._querySummaryTree.clear();
            this._renderQuerySummaryTree(qm.activeQuery.items);
            this._buildReportQuery(qm.activeQuery, qm.activeQueryDataset);
            this._buildQueryLayer(query, qm.activeQueryDataset);
        }
    },

    _onQueryDatasetChanged: function (dataset) {
        console.log(dataset);
        if (this._datasetDropDown)
            this._datasetDropDown.selectByValue(dataset.key, false);

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0))
            qm[0].clearActiveQuery();

        var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
        if ((gm) && (gm.length > 0)) {
            gm = gm[0];

            if (gm.activeGeography)
                this._executeQuery(gm.activeGeography, dataset);
        }

        this._loadCalgaryReports();
    },

    _onQueryDatasetMetadataReceived: function (fieldIndices, bSpatial) {
        if ((!fieldIndices) || (!this._fieldTree))
            return;

        this._fieldTree.clear();

        var field = null;
        var fieldSelected = false, groupExpanded = false;
        for (var fieldGroup in fieldIndices) {
            this._fieldTree.addNode({
                'key': fieldGroup.replace(/^\s*|\s*$/, ''),
                'label': fieldGroup,
                'type': 'branch',
                'selectable': false,
                'expanded': (groupExpanded !== true) ? true : false
            });

            for (var i = 0; field = fieldIndices[fieldGroup].fields[i]; i++) {
                this._fieldTree.addNode({
                    'key': field.name,
                    'parentKey': fieldGroup.replace(/^\s*|\s*$/, ''),
                    'label': field.shortName,
                    'selected': (fieldSelected !== true) ? true : false
                });

                if (fieldSelected !== true)
                    fieldSelected = true;
            }

            if (groupExpanded !== true)
                groupExpanded = true;
        }

        this._onFieldTreeSelectionChanged(this._fieldTree);
    },

    _onQueryDatasetsChanged: function (datasets) {
        if ((!datasets) || (!this._datasetDropDown))
            return;

        this._datasetDropDown.clear();

        var rm = this.componentBus.getComponentReferences('aw.ReportManager');
        if ((rm) && (rm.length > 0)) {
            rm = rm[0];

            if ((this._listDatasets) && (this._listDatasets.length > 0)) {
                var dataset = null;
                for (var i = 0; dataset = this._listDatasets[i]; i++) {
                    rm.removeReports(rm.getReportsBy({ 'type': 'Calgary', 'format': 'List', 'name': dataset.name }), false);
                }
            }

            this._listDatasets = [];
            datasets.sortBy('name');
            var reports = [];
            for (var j = 0; dataset = datasets[j]; j++) {
                this._listDatasets.push(dataset);
                reports.push({ 'format': 'List', 'name': dataset.name, 'type': 'Calgary', 'listOnly': false, 'variant': dataset.key, 'query': '<And/>' });
            }

            rm.addReports(reports);
        }

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((!qm) || (!qm.length > 0))
            return;

        qm = qm[0];
        for (var k = 0; dataset = datasets[k]; k++) {
            this._datasetDropDown.addOption(dataset.key, dataset.name, false, ((dataset === qm.activeQueryDataset) ? true : false));
        }

        var map = this.componentBus.getComponentReferences('aw.ui.Map');
        if ((map) && (map.length > 0)) {
            map = map[0];

            var noCal = true;
            for (var n = 0; dataset = datasets[n]; n++) {
                if ((dataset.variant) && (dataset.variant.toLowerCase().indexOf("userlocationfile:") < 0)) {
                    noCal = false;
                    break;
                }
            }

            var pointDatasetGroup = map.getLayerByKey('pointsets');
            if (noCal) {
                map.removeLayerByKey('pointsets');
            }
            else {
                if (pointDatasetGroup)
                    pointDatasetGroup.removeAllLayers();
                else
                    pointDatasetGroup = map.addLayer(new aw.ui.Map.Layer.Group({ 'key': 'pointsets', 'label': 'RETAILNATION', 'drawPriority': 6 }));

                var retailLayers = new Array(8);
                for (var m = 0; dataset = datasets[m]; m++) {
                    if ((dataset.variant) && (dataset.variant.toLowerCase().indexOf("userlocationfile:") < 0)) {
                        //'icon': './custom/img/Acxiom/RC_regional.png'
                        var layerProperties = { 'Regional': { 'order': '2', 'fillColor': 'ff8040' },
                            'District': { 'order': '5', 'fillColor': '0000ff' },
                            'Local': { 'order': '7', 'fillColor': '808080' },
                            'Major_City': { 'order': '0', 'fillColor': 'ff00ff' },
                            'Major_District': { 'order': '4', 'fillColor': '008040' },
                            'Major_Regional': { 'order': '1', 'fillColor': 'ff0000' },
                            'Minor_District': { 'order': '6', 'fillColor': '00ffff' },
                            'Minor_Local': { 'order': '8', 'fillColor': '8000ff' },
                            'Sub-Regional': { 'order': '3', 'fillColor': 'ffff00' }
                        };
                        //pointDatasetGroup.addLayer(new aw.ui.Map.Layer.Point.Query({ 'key': 'listlayer_' + dataset.key + '_' + dataset.name, 'label': dataset.name, 'labelTemplate': 'QueryLabel', 'labelControllable': true, 'options': false, 'dataset': dataset.key, 'query': '<All/>', 'visible': true, 'drawPriority': pri, 'parameters': { 'fillc': fillColors[dataset.name.replace(" ", "_")], 'outw': 1, 'outc': '00000', 'symst': 'diamond'} }));
                        retailLayers[layerProperties[dataset.name.replace(" ", "_")].order] = { 'key': 'listlayer_' + dataset.key, 'label': dataset.name, 'labelTemplate': 'QueryLabel', 'labelControllable': true, 'options': false, 'dataset': dataset.key, 'query': '<All/>', 'visible': true, 'drawPriority': '5', 'parameters': { 'fillc': layerProperties[dataset.name.replace(" ", "_")].fillColor, 'outw': 1, 'outc': '00000', 'symst': 'diamond'} };
                    }
                }
                for (var p = retailLayers.length - 1; p >= 0; p--) {
                    pointDatasetGroup.addLayer(new aw.ui.Map.Layer.Point.Query(retailLayers[p]));
                }
            }
        }
    },

    _onQuerySaved: function (query, name) {
        if ((this._queryNameLabel) && (name))
            this._queryNameLabel.setValue(name);
    },

    _onSaveQueryClick: function (control) {
        if (this.isSessionValidated() === true) {
            var qm = this.componentBus.getComponentReferences('aw.QueryManager');
            if ((qm) && (qm.length > 0))
                qm[0].saveActiveQuery(null, this._onQuerySaved.bind(this));
        } else {
            new aw.ui.Dialog.Error({ 'title': 'Access Denied', 'content': 'You must be logged in to access this functionality.' });
        }
    },

    _onSummaryTreeSelectionChanged: function (tree) {
        if (this._deleteFilterButton)
            this._deleteFilterButton.disable();

        if (!tree)
            return;

        var selectedKeys = tree.getSelectedKeys();
        if ((!selectedKeys) || (selectedKeys.length !== 1))
            return;

        var selectedKey = selectedKeys[0];

        var qm = this.componentBus.getComponentReferences('aw.QueryManager');
        if ((qm) && (qm.length > 0) && (qm[0].activeQuery))
            qm = qm[0];
        else
            return;

        var filter = qm.activeQuery.getItemById(selectedKey);
        if ((!filter) || (filter.derivesFrom('aw.Query.Filter.Spatial')))
            return;

        if (this._activeFilter === filter)
            return;

        this._activeFilter = filter;
        this._fieldTree.selectNodeByKey(filter.name);

        if (this._deleteFilterButton)
            this._deleteFilterButton.enable();
    },

    _onUserDataActionExecuted: function (parameters) {
        if (!parameters)
            return;

        if (parameters.datatype == 'CalgaryListFilter') {
            this._loadCalgaryReports();

            if (parameters.action == 'Edit') {
                if (!parameters.params)
                    return;

                var qm = this.componentBus.getComponentReferences('aw.QueryManager');
                if ((!qm) || (!qm.length > 0))
                    return;

                qm = qm[0];

                if ((!qm.activeQueryDataset) || (qm.activeQueryDataset.key !== parameters.params.dataset)) {
                    qm.setActiveQueryDatasetByKey(parameters.params.dataset);
                    this._loadQuery_fx = this._loadQuery.bind(this, parameters);
                    qm.registerEvent('ondatasetmetadatareceived', this._loadQuery_fx);
                } else {
                    this._loadQuery(parameters);
                }
            }
        }
    },

    _renderQuerySummaryTree: function (items, parentKey) {
        if ((!items) || (!items.length > 0))
            return;

        var nodes = [];
        var item = null, node = null;

        for (var i = 0; item = items[i]; i++) {
            if (!item.derivesFrom('aw.Query.Filter.Spatial')) {
                this._querySummaryTree.addNode({
                    'key': item.id,
                    'label': item.getSummaryLabel(),
                    'parentKey': (parentKey) ? parentKey : null,
                    'selectable': true
                });

                this._renderQuerySummaryTree(item.items, item.id);
            } else {
                this._renderQuerySummaryTree(item.items, parentKey);
            }
        }
    },

    _setFilterTypeSelect: function (field) {
        if ((!field) || (!field.type) || (!this._filterTypeSelect))
            return;

        this._filterTypeSelect.options.length = 0;

        var bEnumeratedValues = ((field.enumeratedValues) && (field.enumeratedValues.length > 0)) ? true : false;
        var bRangeValues = ((field.rangeValues) && (field.rangeValues.length > 0)) ? true : false;

        var verbs = [];
        if (field.type == 'Contains') {
            verbs.push({ 'verb': 'is', 'label': 'Is...' });
            verbs.push({ 'verb': 'begins', 'label': 'Begins with...' });
            verbs.push({ 'verb': 'contains', 'label': 'Contains...', 'selected': true });
            verbs.push({ 'verb': 'ends', 'label': 'Ends with...' });

            if (bEnumeratedValues === true)
                verbs.push({ 'verb': 'list', 'label': 'Is in List...' });

            verbs.push({ 'verb': 'null', 'label': 'Is Null' });
        } else if ((field.type == 'AString') || (field.type == 'WString')) {
            verbs.push({ 'verb': 'is', 'label': 'Is...', 'selected': true });
            verbs.push({ 'verb': 'begins', 'label': 'Begins with...' });

            if (bRangeValues === true)
                verbs.push({ 'verb': 'range', 'label': 'Is in Range', 'selected': true });

            verbs.push({ 'verb': 'ends', 'label': 'Ends with...' });

            if ((bEnumeratedValues === true) || (field.listTreeEnumerator === true))
                verbs.push({ 'verb': 'list', 'label': 'Is in List...', 'selected': !field.listTreeEnumerator });

            if (field.listTreeEnumerator === true)
                verbs.push({ 'verb': 'listBegin', 'label': 'Begins with value in list...', 'selected': true });
        } else if ((field.type == 'Double') || (field.type == 'Byte') || (field.type == 'Int64') || (field.type == 'Int16') || (field.type == 'Float')) {
            verbs.push({ 'verb': 'is', 'label': 'Is...' });
            verbs.push({ 'verb': 'range', 'label': 'Is in Range', 'selected': true });

            if (bEnumeratedValues === true)
                verbs.push({ 'verb': 'list', 'label': 'Is in List...' });

            verbs.push({ 'verb': 'null', 'label': 'Is Null' });
        }

        var verb = null;
        var selIdx = 0;
        for (var i = 0; verb = verbs[i]; i++) {
            var opt = document.createElement('option');
            opt.text = verb.label;
            opt.value = verb.verb;

            try {
                this._filterTypeSelect.add(opt, null);
            } catch (e) {
                this._filterTypeSelect.add(opt);
            }

            if (verb.selected === true)
                selIdx = i;
        }

        this._filterTypeSelect.selectedIndex = selIdx;
        this._onFilterTypeSelectChanged();
    },

    CLASS_NAME: 'DNow.QueryViewer'
});
