bqc.RESULT_NONE = 'none';
bqc.RESULT_SINGLE = 'single';
bqc.RESULT_MULTIPLE = 'multiple';

bqc.METHOD_FROM = 'applyFrom';
bqc.METHOD_TO = 'applyTo';

bqc.onEnterKey = function(evt, callback) {
    var keyId = (window.event == undefined) ? evt.which : window.event.keyCode;
    if (keyId == 13) {
        callback();
    }
}

bqc.isSet = function(value) {
    return value != null && value.toString().length > 0;
}

bqc.setVisible = function(el, visible) {
    el.style.display = (visible) ? '' : 'none';
}

bqc.RoutingForm = Class.create({

    initialize: function(router) {
        this.router = router;
        this.form = $('routingForm');
        this.listeners = [];

        this.impossibleMessage = $('rfImpossibleMessage');
        this.impossibleMessageSpan = $('rfImpossibleMessageSpan');

        this.fromTable = $('rfFromTable');
        this.fromImpossibleMessage = $('rfFromImpossibleMessage');
        this.fromImpossibleMessageSpan = $('rfFromImpossibleMessageSpan');
        this.fromResult = $('rfFromResult');
        this.fromResultLabel = $('fromResultLabel');
        this.fromInputLabel = $('rfFromInputLabel');
        this.fromInput = $('rfFromInput');
        this.fromButtons = $('rfFromButtons');
        this.fromAddressSearch = $('fromAddressSearch');

        this.toTable = $('rfToTable');
        this.toImpossibleMessage = $('rfToImpossibleMessage');
        this.toImpossibleMessageSpan = $('rfToImpossibleMessageSpan');
        this.toResult = $('rfToResult');
        this.toResultLabel = $('toResultLabel');
        this.toInputLabel = $('rfToInputLabel');
        this.toInput = $('rfToInput');
        this.toButtons = $('rfToButtons');
        this.toAddressSearch = $('toAddressSearch');

        this.fromInputField = $('routingFromAddressInput');
        this.toInputField = $('routingToAddressInput');
        this.buttons = $('rfButtons');

        this.kmButton = $('rfKmButton');
        this.milesButton = $('rfMilesButton');
        this.unitToggler = $('rfUnitToggler');
        this.distances = null;
        this.distancePlaceholders = {};
        this.distancePlaceholders[bqc.METHOD_FROM] = [];
        this.distancePlaceholders[bqc.METHOD_TO] = [];

        this.marker = null;
        this.oldFromAddress = null;
        this.oldToAddress = null;
        this.fromPlacemark = null;
        this.toPlacemark = null;
        this.fromResultType = null;
        this.toResultType = null;

        this.isGoogleAnalyticsDone = false;

        this.initVisibilities();

        this.geocoder = new GClientGeocoder();
        this.geocoder.setBaseCountryCode('ca');
        this.geocoder.setViewport(new GLatLngBounds(new GLatLng(26.745610382199022, -165.05859375), new GLatLng(82.49482361179574, -54.84375)));

        var that = this;
        this.member = {
            id: 'routingForm',
            applyDistances: function() {that.applyDistances();},
            setToKM: function() {that.setUnitToKm();},
            setToMiles: function() {that.setUnitToMiles();}
        }
    },

    setOptions: function(options) {
        if (bqc.isSet(options.routingFromAddress) || bqc.isSet(options.routingToAddress) ||
            bqc.isSet(options.routingFromAddId) || bqc.isSet(options.routingToAddId)) {
            options.r = Math.random();
            var that = this;
            new Ajax.Request('getGeocodeInfo.do', {
                method: 'post',
                parameters: options,
                evalJSON: true,
                onSuccess: function(transport) {
                    that.geocodeParams(transport.responseJSON);
                }
            });
        }
    },

    applyDistances: function() {
        if (this.distances != null) {
            for (var i = 0; i < this.distances.length; ++i) {
                $('rfDist-' + i).innerHTML = metersToCurrentUnit(this.distances[i]);
            }
        }
    },

    setUnitToKm: function() {
        this.kmButton.className = 'nolink';
        this.kmButton.onclick = function() {};
        this.milesButton.className = 'link';
        this.milesButton.onclick = bqc.unitToggler.setToMiles;
        bqc.params.p_unit = 'km';
    },

    setUnitToMiles: function() {
        this.milesButton.className = 'nolink';
        this.milesButton.onclick = function() {};
        this.kmButton.className = 'link';
        this.kmButton.onclick = bqc.unitToggler.setToKM;
        bqc.params.p_unit = 'mi';
    },

    addListener: function(listener) {
        this.listeners.push(listener);
    },

    inform: function(callback) {
        for (var i = 0; i < this.listeners.length; ++i) {
            callback.apply(this, [this.listeners[i]]);
        }
    },

    isVisible: function(el) {
        return el.style.display == null || el.style.display.length == 0;
    },

    setVisibility: function(el, visible) {
        el.style.visibility = (visible) ? 'visible' : 'hidden';
    },

    show: function() {
        bqc.setVisible(this.form, true);
    },

    hide: function() {
        bqc.setVisible(this.form, false);
        this.isGoogleAnalyticsDone = false;
        if (this.isVisible(this.fromImpossibleMessage) ||
            this.isVisible(this.toImpossibleMessage)) {
            this.reset();
        }
    },

    hideFromMessages: function() {
        bqc.setVisible(this.fromImpossibleMessage, false);
        this.closeFromAddressSearch();
    },

    hideToMessages: function() {
        bqc.setVisible(this.toImpossibleMessage, false);
        this.closeToAddressSearch();
    },

    hideMessages: function() {
        this.hideFromMessages();
        this.hideToMessages();
        bqc.setVisible(this.impossibleMessage, false);
    },

    geocodeParams: function(options) {
        this.fromInputField.value = options.from.value;
        this.toInputField.value = options.to.value;
        this.initializing = true;
        this.getDirections(options);
    },

    getDirections: function(options, logOptions) {
        if (logOptions && logOptions.logAnalytics && this.isVisible(this.form) && !this.isGoogleAnalyticsDone) {
            bqc.gaLogger.log(bqc.params.p_mode_org, bqc.GAnalyticsStrings.level2[logOptions.level2Log], bqc.GAnalyticsStrings.level3[logOptions.level3Log]);
            this.isGoogleAnalyticsDone = true;
        }
        var that = this;
        this.fromPlacemark = null;
        this.toPlacemark = null;
        this.fromResultType = null;
        this.toResultType = null;

        this.hideMessages();
        //bqc.gaLogger.log(bqc.params.p_mode_org, bqc.GAnalyticsStrings.level2.routingSearch, bqc.GAnalyticsStrings.level3.map);
        this.geocodeFrom(options, function(fromResultType, fromResult) {
            that.geocodeTo(options, function(toResultType, toResult) {

                if (fromResultType == bqc.RESULT_SINGLE || toResultType == bqc.RESULT_SINGLE) {
                    bqc.setVisible(that.buttons, false);
                }
                if (fromResultType != bqc.RESULT_SINGLE && toResultType == bqc.RESULT_SINGLE) {
                    bqc.setVisible(that.fromButtons, true);
                    if (fromResultType != bqc.RESULT_MULTIPLE) {
                        that.showPoint(toResult, false)
                    }
                } else if (fromResultType == bqc.RESULT_SINGLE && toResultType != bqc.RESULT_SINGLE) {
                    bqc.setVisible(that.toButtons, true);
                    if (toResultType != bqc.RESULT_MULTIPLE) {
                        that.showPoint(fromResult, true)
                    }
                }

                if (fromResultType == bqc.RESULT_MULTIPLE) {
                    that.showSearchResult(that.fromAddressSearch, that.fromImpossibleMessageSpan, fromResult,
                        (toResultType == bqc.RESULT_MULTIPLE) ?
                            null : toResult, bqc.METHOD_FROM);
                }
                if (toResultType == bqc.RESULT_MULTIPLE) {
                    that.showSearchResult(that.toAddressSearch, that.toImpossibleMessageSpan, toResult,
                        (fromResultType == bqc.RESULT_MULTIPLE) ?
                            null : fromResult, bqc.METHOD_TO)
                }
                that.finish();
            }, true);
        }, true);
    },

    createDistance: function(firstPlacemark, secondPlacemark) {
        var meterDist = this.getPoint(firstPlacemark).distanceFrom(this.getPoint(secondPlacemark));
        var dist = metersToCurrentUnit(meterDist);
        var html = '<br><span id="rfDist-' + this.distances.length + '" class="routingListDetailDist">' + dist+ '</span>';
        this.distances.push(meterDist);
        return html;
    },
    
    refreshDistances: function(firstPlacemark, method) {
        var placeholders = this.distancePlaceholders[method];
        for (var i = 0; i < placeholders.length; ++i) {
            var placeholder = placeholders[i];
            $(placeholder.id).innerHTML = this.createDistance(firstPlacemark, placeholder.placemark);
        }
    },

    refreshFromDistances: function(placemark) {
        if (this.fromResultType == bqc.RESULT_MULTIPLE) {
            this.refreshDistances(placemark, bqc.METHOD_FROM);
            return true;
        }
        return false;
    },

    refreshToDistances: function(placemark) {
        if (this.toResultType == bqc.RESULT_MULTIPLE) {
            this.refreshDistances(placemark, bqc.METHOD_TO);
            return true;
        }
        return false;
    },

    geocodeFrom: function(options, callback, dontShow) {
        this.hideFromMessages();
        var that = this;
        this.geocode(this.fromInputField, this.fromInputLabel, this.fromImpossibleMessage, this.fromImpossibleMessageSpan, this.fromResult, this.fromResultLabel, function(fromResultType, fromResult) {
            that.fromPlacemark = fromResult;
            that.fromResultType = fromResultType;
            if (fromResultType == bqc.RESULT_SINGLE) {
                that.refreshToDistances(fromResult);
            }
            callback(fromResultType, fromResult);
        }, (options != null) ? options.from : {}, dontShow);
    },

    geocodeTo: function(options, callback, dontShow) {
        this.hideToMessages();
        var that = this;
        this.geocode(this.toInputField, this.toInputLabel, this.toImpossibleMessage, this.toImpossibleMessageSpan, this.toResult, this.toResultLabel, function(toResultType, toResult) {
            that.toPlacemark = toResult;
            that.toResultType = toResultType;
            if (toResultType == bqc.RESULT_SINGLE) {
                that.refreshFromDistances(toResult);
            }
            callback(toResultType, toResult);
        }, (options != null) ? options.to : {}, dontShow);
    },

    apply: function(address, inputField, addressSearch, impossibleMessage) {
        inputField.value = address;
        addressSearch.innerHTML = address;
        bqc.setVisible(inputField, false);
        bqc.setVisible(addressSearch, true);
        bqc.setVisible(impossibleMessage, false);
    },

    applyFrom: function(index) {
        this.fromPlacemark = this.fromPlacemark[index];
        this.fromPlacemark.displayText = this.fromPlacemark.address;
        this.apply(this.fromPlacemark.address, this.fromInputField, this.fromAddressSearch,
            this.fromImpossibleMessage);
        if (this.refreshToDistances(this.fromPlacemark)) {
            this.showPoint(this.fromPlacemark, true);
        }
        this.fromResultType = bqc.RESULT_SINGLE;
        this.finish();
    },

    applyTo: function(index) {
        this.toPlacemark = this.toPlacemark[index];
        this.toPlacemark.displayText = this.toPlacemark.address;
        this.apply(this.toPlacemark.address, this.toInputField, this.toAddressSearch,
            this.toImpossibleMessage);
        if (this.refreshFromDistances(this.toPlacemark)) {
            this.showPoint(this.toPlacemark, false);
        }
        this.toResultType = bqc.RESULT_SINGLE;
        this.finish();
    },
    
    getFromDirections: function() {
        var that = this;
        this.geocodeFrom(null, function(fromResultType, fromResult) {
            if (fromResultType == bqc.RESULT_SINGLE) {
                bqc.setVisible(that.fromButtons, false);
            } else if (fromResultType == bqc.RESULT_MULTIPLE) {
                that.showSearchResult(that.fromAddressSearch, that.fromImpossibleMessageSpan, fromResult, that.toPlacemark, bqc.METHOD_FROM);
            }
            if (fromResultType == bqc.RESULT_SINGLE) {
                that.finish();
            }
        });
    },

    getToDirections: function() {
        var that = this;
        this.geocodeTo(null, function(toResultType, toResult) {
            if (toResultType != bqc.RESULT_NONE) {
                bqc.setVisible(that.toButtons, false);
                if (toResultType == bqc.RESULT_MULTIPLE) {
                    that.showSearchResult(that.toAddressSearch, that.toImpossibleMessageSpan, toResult, that.fromPlacemark, bqc.METHOD_TO);
                } else {
                    that.finish();
                }
            }
        });
    },

    removeMarker: function() {
        if (this.marker != null) {
            this.router.map.removeOverlay(this.marker);
            this.marker = null;
        }
    },

    geocode: function(field, inputLabel, errorPanel, errorEl, result, resultLabel, callback,
        options, dontShow) {
        var that = this;
        this.removeMarker();
        this.router.remove();
        this.distances = [];
        this.geocoder.getLocations(field.value, function(response) {
            if (response.Placemark != null && (response.Placemark.length == 1 ||
                (response.Placemark.length > 1 && (options != null && options.isLatLon)))) {
                bqc.setVisible(inputLabel, false);
                bqc.setVisible(field, false);
                bqc.setVisible(result, true);

                var placemark = response.Placemark[0];
                field.value = placemark.address;
                resultLabel.innerHTML = placemark.address;
                if (options != null && options.text != null && options.isLatLon) {
                    resultLabel.innerHTML = field.value = options.text;
                }
                placemark.displayText = resultLabel.innerHTML;
                callback(bqc.RESULT_SINGLE, placemark);
            } else if (response.Placemark != null && response.Placemark.length > 1) {
                bqc.setVisible(errorPanel, true);
                if (!dontShow) {
                    that.show();
                }
                callback(bqc.RESULT_MULTIPLE, response.Placemark);
            } else {
                bqc.setVisible(errorPanel, true);
                if (!dontShow) {
                    that.show();
                }
                errorEl.innerHTML = bqc.locale.itinary.form.impossibleMsg;

                callback(bqc.RESULT_NONE);
            }
        });
    },

    showPoint: function(placemark, isStart) {
        if (placemark != null && placemark.Point != null) {
            if (isStart) {
                this.marker = this.router.addStartPoint(this.getPoint(placemark));
            } else {
                this.marker = this.router.addEndPoint(this.getPoint(placemark));
            }
            this.router.map.setCenter(this.marker.getPoint(), bqc.conf.zoomToReference);
        }
    },

    showToggler: function() {
        bqc.unitToggler.addMember(this.member);
        bqc.setVisible(this.unitToggler, true);
    },

    showSearchResult: function(container, errorEl, placemarks, placemark, method) {
        bqc.setVisible(container, true);
        this.showToggler();
        var separator = '<img class="rfListSeparator" src="images/List_Separator.png" />';
        var htmlContent = new String(separator);
        this.showPoint(placemark, method != bqc.METHOD_FROM);
        for (var i = 0; i < placemarks.length; i++) {
            var address = placemarks[i].address;
            var title = address.substring(0, address.indexOf(',', (address.indexOf(',')+1) ));
            if (title != null && title.length == 0) {
                title = address;
            }
            if (placemark != null && placemark.Point != null) {
            }
            htmlContent += '<div><span class="link" class="routingListTitle" onclick="bqc.routingForm.' + method + '(' + i + ');">' + title + '</span>';
            htmlContent += '<br><span class="routingListDetail">' + address + '</span>';
            if (placemark != null && placemark.Point != null) {
                htmlContent += this.createDistance(placemark, placemarks[i]);
            } else {
                var id = 'rfDistPlaceholder-' + method + '-' + i;
                htmlContent += '<span id="' + id + '"></span>';
                this.distancePlaceholders[method].push({
                    id: id,
                    placemark: placemarks[i]
                });
            }
            htmlContent += '</div>' + separator;
        }
        container.innerHTML = htmlContent + '<br>';
        errorEl.innerHTML = bqc.locale.itinary.form.tryMsg;
    },

    getPoint: function(placemark) {
        return new GLatLng(placemark.Point.coordinates[1], placemark.Point.coordinates[0]);
    },

    failed: function() {
        bqc.setVisible(this.impossibleMessage, true);
        this.impossibleMessageSpan.innerHTML = bqc.locale.itinary.noRoute;
        this.isGoogleAnalyticsDone = true;
        this.show();
    },

    finish: function() {
        if (this.fromPlacemark != null && this.fromPlacemark.Point != null &&
            this.toPlacemark != null && this.toPlacemark.Point != null) {
            this.oldFromAddress = this.fromPlacemark.displayText;
            this.oldToAddress = this.toPlacemark.displayText;
            this.inform(function(listener) {
                listener.route(this.fromPlacemark, this.toPlacemark);
            });
            if(!this.initializing){
                bqc.logger.log(null, null, bqc.params.p_mode, bqc.params.p_fromSite, "ACTION_ROUTING_FROM_PROXIMITY", "");
            }
            this.initializing = false;
            this.reset();
            this.hide();
        } else {
            this.show();
        }
    },

    closeAddressSearch: function(addressSearch, methodName) {
        bqc.setVisible(addressSearch, false);
        addressSearch.innerHTML = '';
        this.distancePlaceholders[methodName] = []
    },

    closeFromAddressSearch: function() {
        this.closeAddressSearch(this.fromAddressSearch, bqc.METHOD_FROM);
    },

    closeToAddressSearch: function() {
        this.closeAddressSearch(this.toAddressSearch, bqc.METHOD_TO);
    },

    initVisibilities: function() {
        bqc.setVisible(this.impossibleMessage, false);

        bqc.setVisible(this.fromImpossibleMessage, false);
        bqc.setVisible(this.fromResult, false);
        bqc.setVisible(this.fromInputLabel, true);
        this.closeFromAddressSearch();
        bqc.setVisible(this.fromButtons, false);

        bqc.setVisible(this.toImpossibleMessage, false);
        bqc.setVisible(this.toResult, false);
        bqc.setVisible(this.toInputLabel, true);
        this.closeToAddressSearch();
        bqc.setVisible(this.toButtons, false);

        bqc.setVisible(this.fromInputField, true);
        bqc.setVisible(this.toInputField, true);
        bqc.setVisible(this.buttons, true);

        bqc.setVisible(this.unitToggler, false);
    },

    reset: function() {
        bqc.unitToggler.removeMember(this.member);

        this.fromPlacemark = null;
        this.toPlacemark = null;

        this.fromInputField.value = (this.oldFromAddress == null) ? '' : this.oldFromAddress;
        this.toInputField.value = (this.oldToAddress == null) ? '' : this.oldToAddress;

        this.initVisibilities();

        this.removeMarker();
    },

    fromEnterPressed: function() {
        if (this.isVisible(this.buttons)) {
            this.getDirections(null, {logAnalytics:true,level2Log:'routingSearch',level3Log:'map'});
        } else {
            this.getFromDirections();
        }
    },

    toEnterPressed: function() {
        if (this.isVisible(this.buttons)) {
            this.getDirections(null, {logAnalytics:true,level2Log:'routingSearch',level3Log:'map'});
        } else {
            this.getToDirections();
        }
    }
});
