public static bool IsPrerequisiteUnlockPresent(Commander comm, Unlock unlock)
 {
     if (!string.IsNullOrEmpty(unlock.RequiredInstalledUnlockIDs))
     {
         var requiredUnlockIDs = unlock.RequiredInstalledUnlockIDs.Split(',').Select(int.Parse);
         if (!comm.CommanderModules.Any(x => requiredUnlockIDs.Contains(x.ModuleUnlockID)))
             return false;
     }
     return true;
 }
		public ActionResult CommanderProfile(int profileNumber, string name, int? chassis, string deleteCommander)
		{
			if (profileNumber < 1 || profileNumber > GlobalConst.CommanderProfileCount) return Content("WTF! get lost");

			var db = new ZkDataContext();
			using (var scope = new TransactionScope())
			{

				var unlocks = db.AccountUnlocks.Where(x => x.AccountID == Global.AccountID);

				Commander comm = db.Commanders.SingleOrDefault(x => x.ProfileNumber == profileNumber && x.AccountID == Global.AccountID);
				if (comm != null)
				{
					if (!string.IsNullOrEmpty(deleteCommander)) // delete commander
					{
						db.Commanders.DeleteOnSubmit(comm);
						db.SubmitChanges();
						scope.Complete();
						return GetCommanderProfileView(db, profileNumber);
					}
				}
				else
				{
					comm = new Commander() { AccountID = Global.AccountID, ProfileNumber = profileNumber };
					db.Commanders.InsertOnSubmit(comm);
				}

				if (comm.Unlock == null)
				{
					var chassisUnlock = unlocks.FirstOrDefault(x => x.UnlockID == chassis);
					if ((chassis == null || chassisUnlock == null)) return GetCommanderProfileView(db, profileNumber);
					else
					{
						comm.ChassisUnlockID = chassis.Value;
						comm.Unlock = chassisUnlock.Unlock;
					}
				}

                if (!string.IsNullOrEmpty(name))
                {
                    if (name.Length > 50) name = name.Substring(0, 50);
                    name = Regex.Replace(name, @"[^\u0000-\u007F]", string.Empty); // remove unicode stuff
                    comm.Name = name;
                }

                // process modules
				foreach (var key in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
				{
					var m = Regex.Match(key, "m([0-9]+)");
					if (m.Success)
					{
						var slotId = int.Parse(m.Groups[1].Value);
						int unlockId;
						int.TryParse(Request.Form[key], out unlockId);

						if (unlockId > 0)
						{
							CommanderSlot slot = db.CommanderSlots.Single(x => x.CommanderSlotID == slotId);
							Unlock unlock = db.Unlocks.Single(x => x.UnlockID == unlockId);

							if (!unlocks.Any(x => x.UnlockID == unlock.UnlockID)) return Content("WTF get lost!");
							if (slot.MorphLevel < unlock.MorphLevel || slot.UnlockType != unlock.UnlockType) return Content(string.Format("WTF cannot use {0} in slot {1}", unlock.Name, slot.CommanderSlotID));
							if (!string.IsNullOrEmpty(unlock.LimitForChassis))
							{
								var validChassis = unlock.LimitForChassis.Split(',');
								if (!validChassis.Contains(comm.Unlock.Code)) return Content(string.Format("{0} cannot be used in commander {1}", unlock.Name, comm.Unlock.Name));
							}

							var comSlot = comm.CommanderModules.SingleOrDefault(x => x.SlotID == slotId);
							if (comSlot == null)
							{
								comSlot = new CommanderModule() { SlotID = slotId };
								comm.CommanderModules.Add(comSlot);
							}
							comSlot.ModuleUnlockID = unlockId;
						}
						else
						{
							var oldModule = comm.CommanderModules.FirstOrDefault(x => x.SlotID == slotId);
							if (oldModule != null) comm.CommanderModules.Remove(oldModule);
						}
					}
				}

                // process decorations
                foreach (var key in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
                {
                    var d = Regex.Match(key, "d([0-9]+)");
                    if (d.Success)
                    {
                        var slotId = int.Parse(d.Groups[1].Value);
                        int unlockId;
                        int.TryParse(Request.Form[key], out unlockId);

                        if (unlockId > 0)
                        {
                            CommanderDecorationSlot decSlot = db.CommanderDecorationSlots.Single(x => x.CommanderDecorationSlotID == slotId);
                            Unlock unlock = db.Unlocks.Single(x => x.UnlockID == unlockId);

                            if (!unlocks.Any(x => x.UnlockID == unlock.UnlockID)) return Content("WTF get lost!");
                            if (!string.IsNullOrEmpty(unlock.LimitForChassis))
                            {
                                var validChassis = unlock.LimitForChassis.Split(',');
                                if (!validChassis.Contains(comm.Unlock.Code)) return Content(string.Format("{0} cannot be used in commander {1}", unlock.Name, comm.Unlock.Name));
                            }

                            var comSlot = comm.CommanderDecorations.SingleOrDefault(x => x.SlotID == slotId);
                            if (comSlot == null)
                            {
                                comSlot = new CommanderDecoration() { SlotID = slotId };
                                comm.CommanderDecorations.Add(comSlot);
                            }
                            comSlot.DecorationUnlockID = unlockId;
                        }
                        else
                        {
                            var oldDecoration = comm.CommanderDecorations.FirstOrDefault(x => x.SlotID == slotId);
                            if (oldDecoration != null) comm.CommanderDecorations.Remove(oldDecoration);
                        }
                    }
                }

                // remove a module/decoration if ordered to
                foreach (var toDel in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x)))
                {
					var m = Regex.Match(toDel, "deleteSlot([0-9]+)");
					if (m.Success)
					{
						var slotId = int.Parse(m.Groups[1].Value);
						comm.CommanderModules.Remove(comm.CommanderModules.SingleOrDefault(x => x.SlotID == slotId));
					}
                
                    var d = Regex.Match(toDel, "deleteDecorationSlot([0-9]+)");
                    if (d.Success)
                    {
                        var decSlotId = int.Parse(d.Groups[1].Value);
                        comm.CommanderDecorations.Remove(comm.CommanderDecorations.SingleOrDefault(x => x.SlotID == decSlotId));
                    }
                }

				db.SubmitChanges();
				foreach (var unlock in comm.CommanderModules.GroupBy(x => x.Unlock))
				{
					if (unlock.Key == null) continue;
					var owned = unlocks.Where(x => x.UnlockID == unlock.Key.UnlockID).Sum(x => (int?)x.Count) ?? 0;
					if (owned < unlock.Count())
					{
						var toRemove = unlock.Count() - owned;

						foreach (var m in unlock.OrderByDescending(x => x.SlotID))
						{
							db.CommanderModules.DeleteOnSubmit(m);
							//comm.CommanderModules.Remove(m);
							toRemove--;
							if (toRemove <= 0) break;
						}
					}
				}

				db.SubmitChanges();
				scope.Complete();
			}

			return GetCommanderProfileView(db, profileNumber);
		}