if (typeof(LocationTable) == "undefined") {
    // Only define if it doesn't already exist- this way multiple LocationPanels can share LocationTables
    var LocationTable = new new Class({
        initialize: function() {
            this.locations= [];
            this.fetchedChildren= [];
        },
        haveFetched: function(locId) {
            return (this.fetchedChildren.indexOf(locId) > -1)
        },
        setFetched: function(locId) {
            this.fetchedChildren[this.fetchedChildren.length] = locId;
        },
        getLocation: function(locId) {
            for (x=0;x<this.locations.length;x++) {
                if (this.locations[x].LocationId == locId) {
                    return this.locations[x];
                    break;
                }
            }
        },
        getChildLocations: function(locId) {
            var locArray = [];
            for(xinc=0;xinc<this.locations.length;xinc++) {
                if (this.locations[xinc].ParentId == locId) {
                    locArray[locArray.length] = this.locations[xinc];
                }
            }
            return locArray;
        },
        addLocations: function(json) {
            this.locations.extend(json);
        }
    });
}
var DropDownHandler = new Class({
    initialize: function(arguments) {
        this.dropdowns = arguments.dropdowns;
        this.holder = this.dropdowns[0].getParent();
        $$(this.dropdowns).addEvent("change",this.DropDownChanged.bindWithEvent(this));
        this.valueHolder = arguments.valueholder;
        this.options = JSON.decode(this.valueHolder.value);
        this.rootLocationChangedEvents = [];
        if (arguments.container) {
            this.container = arguments.container;
        }
        if (arguments.validator) {
            this.validator = arguments.validator;
            this.validator.store("handler",this);
        }
        window.addEvent("domready",this.RefreshDropdownIndexes.bind(this));
		//this.SetupDropDowns();
		this.SetHasLocations();
		
		
		
		
    },
	
	SetupDropDowns: function() {
		this.dropdowns.each(function(d){
			
			var span = $(d).getParent();
			var rightBlock = new Element("div", {
				"class": "rightblock"
			})
			span.adopt(rightBlock);
			});
		
	},
	
    Hide: function() {
        this.holder.setStyle("display","none");
    },
    GetOption: function(key) {
        return this.options[key];
    },
    SetOption: function(key,value) {
     
        this.options[key] = value;
        this.valueHolder.value = JSON.encode(this.options);
    },
    GetSelectedId: function() {
        if (this.GetOption("LocationID") != null) {
            return parseInt(this.GetOption("LocationID"));
        } else {
            return 0;
        }
        
    },
    Validate: function(sender,args) {
        
        // non ASP.NET call
        if (typeof(args) == "undefined") {
            if (this.GetSelectedId() != 0) {
                return true;
            } else {
                return false;
            }
        } else // ASP.NET call
        {
            if (this.GetSelectedId() != 0) {
                args.IsValid = true;
            } else {
                args.IsValid = false;
            }
        }
    },
    RefreshDropdownIndexes: function(e) {
        // Override browser default behaviour to restore dropdowns- it confuses things a lot.
        for (var x=0;x<this.dropdowns.length;x++) {
            var selIndex = 0;
            var options = this.dropdowns[x].options;
            for (y=0;y<options.length;y++) {
                if (options[y].defaultSelected == true) {
                    selIndex = y;
                  }
            }
            if (this.dropdowns[x].selectedIndex != selIndex) {
                this.dropdowns[x].selectedIndex = selIndex;
            }
            if (this.dropdowns[x].options.length == 1) {
                this.dropdowns[x].set("disabled",true);
            }
            if (
                (this.dropdowns[x].options.length == 2 && this.GetOption("ShowAllCitiesOption") == null) ||
                (this.dropdowns[x].options.length == 3 && this.GetOption("ShowAllCitiesOption") == true)
               ) {
                
                this.dropdowns[x].selectedIndex = 1;
                this.dropdowns[x].fireEvent("change", {target:this.dropdowns[x]});

            }
        }
    }, 
    IsLocationSuccessful: function(loc) {
        if (this.GetOption("DropDownBehavior") == "PostcodeIsCityLocations") {
            if (loc.IsCity == true) {
                
                return true;
            } else {
                return false
            }
        } else if (this.GetOption("DropDownBehavior") == "SelectToCityLevel") {
            if (loc.CityId == loc.LocationId) {
                return true;
            } else {
                return false;
            }
        
        } else if (this.GetOption("DropDownBehavior") == "SelectToDepth") {
            if (loc.Depth == this.GetOption("SelectionDepth") || !loc.HasChildren) {
                return true;
            } else {
                return false;
            }
        } else if (this.GetOption("DropDownBehavior") == "SelectIsCityLocations" ) {
            // Only valid ones are returned.
            return true;
        }
    },
    GoToAllCities: function(i) {
        if (i == 0) {
            window.location = "/" + this.GetOption("AllCitiesString");
        } else if (i == 1){
            var parentLocation = LocationTable.getLocation(this.dropdowns[0].getChildren()[this.dropdowns[0].selectedIndex].value);
            window.location = "/" + this.GetOption("AllCitiesString") + "/" + parentLocation.SeoName;
        }
    },
    DropDownChanged: function(e) {
		
        var i = this.dropdowns.indexOf(e.target);
        var selectedLocationID = parseInt(this.dropdowns[i].getChildren()[this.dropdowns[i].selectedIndex].value);
        if (selectedLocationID == -1) {
            this.GoToAllCities(i);
            return false;
        }
        var selectedLocation = LocationTable.getLocation(selectedLocationID);
        this.wipeChildrenOf(i);
        this.SetOption("LocationID",0);
        
        if (selectedLocation != null && this.IsLocationSuccessful(selectedLocation)) {
            this.SetOption("LocationID",selectedLocation.LocationId);
        }
        else if (selectedLocation != null && !this.IsLocationSuccessful(selectedLocation)) {
            // If we have a valid LocationID that is not a City
            this.SetOption("LocationID",0);
            this.dropdowns[i + 1].set({
                    disabled: true,
                    styles: {"display":"inline"}
                });
            this.dropdowns[i].set("disabled",true);
            this.dropdowns[i + 1].getChildren("option[value!=0]").dispose();
            this.dropdowns[i + 1].getChildren()[0].set("html","Loading...");
            if (LocationTable.haveFetched(selectedLocationID) == true) {
                // We already have the values- let's build a list programatically and pass it on.
                var locations = LocationTable.getChildLocations(selectedLocationID);
				this.wipeChildrenOf(i+1);
                this.addValues({"json":locations},{"targetDrop": i + 1, "parentLocationID": selectedLocationID});
            } else {
                // We don't already have the values- do a fetch
                if (this.GetOption("DropDownBehavior") == "PostcodeIsCityLocations") {
                    
                    new AjaxProRequest({
                        nSpace: "Erm.Web.Controls.Common.LocationPanel",
                        methodName: "GetIsCityChildrenAjax",
                        arguments: {"locationId": selectedLocationID, "targetDepth": 3},
                        onSuccess: this.addValues.bind(this),
                        onSuccessParams: {"targetDrop": i + 1, "parentLocationID": selectedLocationID, methodUsed: "GetIsCityChildrenAjax"}
                    }).send();
                } else {
                    new AjaxProRequest({
                        nSpace: "Erm.Web.Controls.Common.LocationPanel",
                        methodName: "GetChildrenAjax",
                        arguments: {"locationId": selectedLocationID},
                        onSuccess: this.addValues.bind(this),
                        onSuccessParams: {"targetDrop": i + 1, "parentLocationID": selectedLocationID, methodUsed: "GetChildrenAjax"}
                    }).send();
                }
            }
            }
        if (this.hasCustomEvents && Browser.Engine.trident) {
            e.target.blur();
        }
    },
    addValues: function(data, params) {
        
        LocationTable.addLocations(data.json);
        if (params.parentLocationID && params.methodUsed != "GetIsCityChildrenAjax") {
            LocationTable.setFetched(params.parentLocationID);
        } 
        
        for (var x = 0;x<data.json.length;x++) {
            var option = new Element("option",{
                value: data.json[x].LocationId,
                html: data.json[x].LocationName
            });
            this.dropdowns[params.targetDrop].adopt(option);
            if (data.json[x].Selected) {
                option.set("selected",true);
            }
        }
        
        if (this.GetOption("ShowAllCitiesOption") == true && params.methodUsed == "GetIsCityChildrenAjax") {
            var option = new Element("option",{
                value: "-1",
                html: captable[1097]+"..."
            });
            this.dropdowns[params.targetDrop].adopt(option);
        }
        
        
        if (params.targetDrop > 0) {
            this.dropdowns[params.targetDrop - 1].set("disabled",false);
        }
        this.dropdowns[params.targetDrop].set("disabled",false);
        if (this.GetOption("DropDownBehavior") == "PostcodeIsCityLocations") {
            this.dropdowns[params.targetDrop].getChildren()[0].set("html",this.GetDepthCaption("IsCity")+"...");
        } else if (data.json.length > 0) {
            this.dropdowns[params.targetDrop].getChildren()[0].set("html",this.GetDepthCaption(data.json[0].Depth)+"...");
        }
        if (this.dropdowns[params.targetDrop].getStyle("display") == "none") {
            this.dropdowns[params.targetDrop].setStyle("display","inline");
        }
    },
    wipeChildrenOf: function(i) {
        for (var x = i + 1;x<this.dropdowns.length;x++) {
            this.dropdowns[x].set({
                disabled: true,
                styles: {"display":"none"}
            });
            this.dropdowns[x].getChildren("option[value!=0]").dispose();
        }
    },
    addEvent: function(label,func,args) {

        if (label == "dropdownchanged") {
            var action;
            if (Browser.Engine.trident) {
                // This has to be blur because IE is terrible. It adds events in the wrong order, so we have to force
                // an event that follows change.
                /// TODO: Change this when Mootools 1.3 is released.
                action = "blur";
            } else {
                action = "change";
            }
            for (var x=0;x<this.dropdowns.length;x++) {
                this.dropdowns[x].addEvent(action,func.pass([this,args]));
            }
            this.hasCustomEvents = true;
        }
        else if (label == "rootlocationchanged") {
            this.rootLocationChangedEvents[this.rootLocationChangedEvents.length] = func;
        }
    },
    
    // Basically reload the control
    RefreshSelectedLocation: function() {
        for (x=0;x<this.dropdowns.length;x++) {
            this.dropdowns[x].selectedIndex = 0;
            this.dropdowns[x].set("disabled",true);
            this.dropdowns[x].getChildren()[0].set("html","...");
        }
        
        new AjaxProRequest({
            nSpace: "Erm.Web.Controls.Common.LocationPanel",
            methodName: "RefreshLocations",
            arguments: {"locationId": this.GetOption("LocationID"),"rootIdentifier": this.GetOption("RootLocationID")},
            onSuccess: function(obj) {
                var locationlist = obj.json;
                LocationTable.addLocations([locationlist.RootLocation]);
                this.RootLocation = LocationTable.getLocation(locationlist.RootLocation.LocationId);
                this.wipeChildrenOf(-1);
                this.RefreshSelectedLocationIterate(locationlist.Results,0);
				this.SetHasLocations();
				if (!this.hasLocations) {
					this.SetOption("LocationID",this.GetOption("RootLocationID"));
				}
                for (x=0;x<this.rootLocationChangedEvents.length;x++) {
                    this.rootLocationChangedEvents[x].run(this);
                }
            }.bind(this)
          
        }).send();
    },
        
    RefreshSelectedLocationIterate: function(json, depth) {
       this.addValues({"json":json},{"targetDrop": depth, "parentLocationID": null});
       for (var x=0;x<json.length;x++) {
             if ($defined(json[x].ChildLocations)) {
                    this.RefreshSelectedLocationIterate(json[x].ChildLocations,depth + 1);
                
             }       
       }
       
        if (this.zipHandler != null) {
            if (this.zipHandler.waiterVisible) {
                this.zipHandler.Waiter("hide");
            }
        }
		
       
        
    },
    ControlDisabledState: function(state) {
        for (x=0;x<this.dropdowns.length;x++) {
            this.dropdowns[x].set("disabled",state);
        }
    },
	SetHasLocations: function() {
		if (this.dropdowns[0].getChildren().length == 1) {
			this.hasLocations = false;
			

		} else {
			this.hasLocations = true;

		}
	},
	
	GetDepthCaption: function(depth) {
        if (typeof(depth) == "number") {
            depth = String(depth+"");
        }
       
        var ret;
        switch (depth) {
            case "1": { ret = captable[1087]; break; }
            case "2": { ret = captable[1088]; break; }
            case "3": { ret = captable[1089]; break; }
            case "4": { ret = captable[1090]; break; }
            case "5": { ret = captable[1091]; break; }
            case "IsCity": { ret = captable[1092]; break; }
        }
        return ret;
   }
});
