public ICollection<UpgradeDef> GetAvailableUpgrades(Galaxy galaxy, string playerName)
		{
			var player = Galaxy.GetPlayer(playerName);
			var availableUpgrades = new List<UpgradeDef>();
			var allUpgrades = new Upgrades().UpgradeDefs;
			foreach (var upgradeDef in allUpgrades) {
				if (upgradeDef.Cost <= player.MetalAvail && upgradeDef.FactionName == player.FactionName) {
					List<UpgradeDef> upgrades;
					if (!UpgradeData.TryGetValue(playerName, out upgrades)) {
						upgrades = new List<UpgradeDef>();
					}

					var lesserUpgrade =
						allUpgrades.Where(
							x =>
							x.FactionName == upgradeDef.FactionName && x.Branch == upgradeDef.Branch && x.Division == upgradeDef.Division &&
							x.Level == upgradeDef.Level - 1).SingleOrDefault();

					var hasLesserUpgrade = lesserUpgrade == null || upgrades.Where(x => x.ID == lesserUpgrade.ID).Any();

					if (hasLesserUpgrade) {
						availableUpgrades.Add(upgradeDef);
					}
				}
			}
			return availableUpgrades;
		}
		public void BuyUpgrade(AuthInfo login, int upgradeDefID, string choice)
		{
			if (!ValidateLogin(login)) {
				throw new Exception("Login failed");
			}
			var udef = new Upgrades().UpgradeDefs.Where(x => x.ID == upgradeDefID).SingleOrDefault();
			if (udef == null || !udef.UnitDefs.Where(x => x.Name == choice).Any()) {
				throw new Exception("No such upgrade definition found");
			}
			// remove upgrade of same level or id if it already exists
			List<UpgradeDef> existing;
			if (UpgradeData.TryGetValue(login.Login, out existing)) {
				var todel =
					existing.Where(
						x => x.ID == upgradeDefID || x.Level == udef.Level && x.Branch == udef.Branch && x.Division == udef.Division).
						ToList();

				foreach (var x in todel) {
					existing.Remove(x);
				}
			}

			var copy = udef.BuyCopy();
			copy.UnitChoice = choice;
            var player = Galaxy.GetPlayer(login.Login);

			if (copy.IsSpaceShip) {
				
				var planet = Galaxy.GetPlanet(player.Name);
				Planet targetPlanet = null;
				if (planet != null && planet.FactionName == player.FactionName) {
					targetPlanet = planet;
				} else {
					targetPlanet =
						Galaxy.Planets.Where(x => x.FactionName == player.FactionName).OrderBy(
							x => Galaxy.GetPlayer(x.OwnerName).RankOrder).FirstOrDefault();
				}
				if (targetPlanet == null) {
					throw new Exception("Cannot find suitable planet for the fleet");
				}

				var fleet = new SpaceFleet
				{TargetPlanetID = targetPlanet.ID, Destination = targetPlanet.Position, OwnerName = player.Name};
				Galaxy.Fleets.Add(fleet);
				copy.Purchased++;
			}

			if (existing == null) {
				existing = new List<UpgradeDef>();
			}
			existing.Add(copy);
            player.PurchaseHistory.Add(new PurchaseData(upgradeDefID, choice));
			UpgradeData[login.Login] = existing;
			Galaxy.GetPlayer(login.Login).MetalSpent += copy.Cost;
			SaveState();
		}