/
com/planet_ink/coffee_mud/Abilities/Common/
com/planet_ink/coffee_mud/Abilities/Diseases/
com/planet_ink/coffee_mud/Abilities/Druid/
com/planet_ink/coffee_mud/Abilities/Fighter/
com/planet_ink/coffee_mud/Abilities/Languages/
com/planet_ink/coffee_mud/Abilities/Misc/
com/planet_ink/coffee_mud/Abilities/Prayers/
com/planet_ink/coffee_mud/Abilities/Properties/
com/planet_ink/coffee_mud/Abilities/Skills/
com/planet_ink/coffee_mud/Abilities/Songs/
com/planet_ink/coffee_mud/Abilities/Spells/
com/planet_ink/coffee_mud/Abilities/Thief/
com/planet_ink/coffee_mud/Abilities/Traps/
com/planet_ink/coffee_mud/Behaviors/
com/planet_ink/coffee_mud/CharClasses/interfaces/
com/planet_ink/coffee_mud/Commands/
com/planet_ink/coffee_mud/Commands/interfaces/
com/planet_ink/coffee_mud/Common/
com/planet_ink/coffee_mud/Common/interfaces/
com/planet_ink/coffee_mud/Exits/interfaces/
com/planet_ink/coffee_mud/Items/Armor/
com/planet_ink/coffee_mud/Items/Basic/
com/planet_ink/coffee_mud/Items/CompTech/
com/planet_ink/coffee_mud/Items/MiscMagic/
com/planet_ink/coffee_mud/Items/Weapons/
com/planet_ink/coffee_mud/Items/interfaces/
com/planet_ink/coffee_mud/Libraries/
com/planet_ink/coffee_mud/Libraries/interfaces/
com/planet_ink/coffee_mud/Locales/
com/planet_ink/coffee_mud/MOBS/
com/planet_ink/coffee_mud/Races/
com/planet_ink/coffee_mud/Races/interfaces/
com/planet_ink/coffee_mud/WebMacros/
com/planet_ink/coffee_mud/WebMacros/interfaces/
com/planet_ink/coffee_mud/core/
com/planet_ink/coffee_mud/core/collections/
com/planet_ink/coffee_mud/core/interfaces/
com/planet_ink/coffee_mud/core/intermud/
com/planet_ink/coffee_mud/core/intermud/i3/
com/planet_ink/coffee_web/server/
com/planet_ink/siplet/applet/
lib/
resources/factions/
resources/fakedb/
resources/progs/autoplayer/
resources/quests/holidays/
web/
web/admin.templates/
web/admin/grinder/
web/admin/images/
web/clan.templates/
web/pub.templates/
web/pub/images/mxp/
web/pub/sounds/
web/pub/textedit/
package com.planet_ink.coffee_mud.Commands;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.collections.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.ExpertiseLibrary.ExpertiseDefinition;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;

import java.util.*;

/*
   Copyright 2004-2016 Bo Zimmerman

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

	   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
@SuppressWarnings("rawtypes")
public class Qualify  extends Skills
{
	public Qualify(){}

	private final String[] access=I(new String[]{"QUALIFY","QUAL"});
	@Override public String[] getAccessWords(){return access;}
	
	protected final static int SKILL_ANY=-1;
	protected final static int SKILL_CRAFTING_ONLY=-2;
	protected final static int SKILL_BUILDING_ONLY=-3;
	protected final static int SKILL_GATHERING_ONLY=-4;

	public StringBuffer getQualifiedAbilities(MOB viewerM,
											  MOB ableM,
											  int ofType,
											  int ofDomain,
											  String prefix,
											  boolean shortOnly)
	{
		/*
		final HashSet<Integer> V=new HashSet<Integer>();
		int mask=Ability.ALL_ACODES;
		if(ofDomain>=0)
		{
			mask=Ability.ALL_ACODES|Ability.ALL_DOMAINS;
			ofType=ofType|ofDomain;
		}
		V.add(Integer.valueOf(ofType));
		&&(ofTypes.contains(Integer.valueOf(A.classificationCode()&mask)))
		*/
		
		final int checkCode = ofType;
		final int badDomain;
		final int checkDomain;
		switch(ofDomain)
		{
		case SKILL_CRAFTING_ONLY:
			badDomain = -1;
			checkDomain = Ability.DOMAIN_CRAFTINGSKILL;
			break;
		case SKILL_GATHERING_ONLY:
			badDomain = Ability.DOMAIN_CRAFTINGSKILL;
			checkDomain = -1;
			break;
		case SKILL_BUILDING_ONLY:
			badDomain = -1;
			checkDomain = Ability.DOMAIN_BUILDINGSKILL;
			break;
		case SKILL_ANY:
		case 0:
			badDomain = -1;
			checkDomain = -1;
			break;
		default:
			badDomain = -1;
			checkDomain = ofDomain;
		}
		
		final Filterer<Ability> newFilter=new Filterer<Ability>()
		{
			@Override
			public boolean passesFilter(Ability A) 
			{
				if((A.classificationCode() & Ability.ALL_ACODES) != checkCode)
					return false;
				if((A.classificationCode() & Ability.ALL_DOMAINS) == badDomain)
					return false;
				if((checkDomain > 0) && ((A.classificationCode() & Ability.ALL_DOMAINS) != checkDomain))
					return false;
				return true;
			}
		};
		return getQualifiedAbilities(viewerM,ableM,newFilter,prefix,shortOnly);
	}

	public StringBuffer getQualifiedAbilities(MOB viewerM,
											  MOB ableM,
											  Filterer<Ability> filter,
											  String prefix,
											  boolean shortOnly)
	{
		int highestLevel=0;
		final StringBuffer msg=new StringBuffer("");
		final boolean checkUnMet=ableM.charStats().getCurrentClass().showThinQualifyList();
		for(final Enumeration<Ability> a=CMClass.abilities();a.hasMoreElements();)
		{
			final Ability A=a.nextElement();
			final int level=CMLib.ableMapper().qualifyingLevel(ableM,A);
			if((CMLib.ableMapper().qualifiesByLevel(ableM,A))
			&&(!CMLib.ableMapper().getSecretSkill(ableM,A.ID()))
			&&(level>highestLevel)
			&&(level<(CMLib.ableMapper().qualifyingClassLevel(ableM,A)+1))
			&&(filter.passesFilter(A))
			&&(CMLib.ableComponents().getCommonSkillRemainder(ableM, A).specificSkillLimit() > 0)
			&&(ableM.fetchAbility(A.ID())==null)
			&&(!checkUnMet || CMLib.ableMapper().getUnmetPreRequisites(ableM,A).size()==0))
				highestLevel=level;
		}
		int col=0;
		final int COL_LEN1=CMLib.lister().fixColWidth(3.0,viewerM);
		final int COL_LEN2=CMLib.lister().fixColWidth(19.0,viewerM);
		final int COL_LEN3=CMLib.lister().fixColWidth(12.0,viewerM);
		final int COL_LEN4=CMLib.lister().fixColWidth(13.0,viewerM);
		for(int l=0;l<=highestLevel;l++)
		{
			final StringBuffer thisLine=new StringBuffer("");
			for(final Enumeration<Ability> a=CMClass.abilities();a.hasMoreElements();)
			{
				final Ability A=a.nextElement();
				if((CMLib.ableMapper().qualifiesByLevel(ableM,A))
				   &&(CMLib.ableMapper().qualifyingLevel(ableM,A)==l)
				   &&(!CMLib.ableMapper().getSecretSkill(ableM,A.ID()))
				   &&(ableM.fetchAbility(A.ID())==null)
				   &&(filter.passesFilter(A))
				   &&(CMLib.ableComponents().getCommonSkillRemainder(ableM, A).specificSkillLimit() > 0)
				   &&(!checkUnMet || CMLib.ableMapper().getUnmetPreRequisites(ableM,A).size()==0))
				{
					if((++col)>2)
					{
						thisLine.append("\n\r");
						col=1;
					}
					thisLine.append("^N[^H"+CMStrings.padRight(""+l,COL_LEN1)+"^?] "
										   +CMStrings.padRight("^<HELP^>"+A.name()+"^</HELP^>",COL_LEN2)+" "
										   +CMStrings.padRight(A.requirements(viewerM),(col==2)?COL_LEN3:COL_LEN4));
				}
			}
			if(thisLine.length()>0)
			{
				if(msg.length()==0)
					msg.append(L("\n\r^N[^HLvl^?] Name                Requires     [^HLvl^?] Name                Requires\n\r"));
				msg.append(thisLine);
			}
		}
		if(msg.length()==0)
			return msg;
		msg.insert(0,prefix);
		msg.append("\n\r");
		return msg;
	}

	@Override
	public boolean execute(MOB mob, List<String> commands, int metaFlags)
		throws java.io.IOException
	{
		final StringBuffer msg=new StringBuffer("");
		final String qual=CMParms.combine(commands,1).toUpperCase();
		final boolean shortOnly=false;
		final boolean showAll=qual.length()==0;
		if(showAll||("SKILLS".startsWith(qual)))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_SKILL,SKILL_ANY,"\n\r^HGeneral Skills:^? ",shortOnly));
		if(showAll||("COMMON SKILLS").startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_COMMON_SKILL,SKILL_ANY,"\n\r^HCommon Skills:^? ",shortOnly));
		else if ("CRAFTING SKILLS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_COMMON_SKILL,SKILL_CRAFTING_ONLY,"\n\r^HCrafting Skills:^? ",shortOnly));
		else if ("BUILDING SKILLS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_COMMON_SKILL,SKILL_BUILDING_ONLY,"\n\r^HBuilding Skills:^? ",shortOnly));
		else if ("GATHERING SKILLS".startsWith(qual)
			||"NON CRAFTING SKILLS".startsWith(qual)||"NON-CRAFTING SKILLS".startsWith(qual)||"NONCRAFTING SKILLS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_COMMON_SKILL,SKILL_GATHERING_ONLY,"\n\r^HNon-Crafting Common Skills:^? ",shortOnly));
		if(showAll||("THIEVES SKILLS".startsWith(qual))||"THIEF SKILLS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_THIEF_SKILL,SKILL_ANY,"\n\r^HThief Skills:^? ",shortOnly));
		if(showAll||"SPELLS".startsWith(qual)||"MAGE SPELLS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_SPELL,SKILL_ANY,"\n\r^HSpells:^? ",shortOnly));
		if(showAll||"PRAYERS".startsWith(qual)||"CLERICAL PRAYERS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_PRAYER,SKILL_ANY,"\n\r^HPrayers:^? ",shortOnly));
		if(showAll||"POWERS".startsWith(qual)||"SUPER POWERS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_SUPERPOWER,SKILL_ANY,"\n\r^HSuper Powers:^? ",shortOnly));
		if(showAll||"TECHS".startsWith(qual)||"TECH SKILLS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_TECH,SKILL_ANY,"\n\r^HTech Skills:^? ",shortOnly));
		if(showAll||"CHANTS".startsWith(qual)||"DRUID CHANTS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_CHANT,SKILL_ANY,"\n\r^HDruidic Chants:^? ",shortOnly));
		if(showAll||"SONGS".startsWith(qual)||"BARD SONGS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_SONG,SKILL_ANY,"\n\r^HSongs:^? ",shortOnly));
		if(showAll||"LANGUAGES".startsWith(qual)||"LANGS".startsWith(qual))
			msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_LANGUAGE,SKILL_ANY,"\n\r^HLanguages:^? ",shortOnly));
		int domain=-1;
		String domainName="";
		if(!showAll)
		{
			for(int i=1;i<Ability.DOMAIN_DESCS.length;i++)
			{
				if (Ability.DOMAIN_DESCS[i].startsWith(qual.toUpperCase()))
				{
					domain = i << 5;
					break;
				}
				else 
				if ((Ability.DOMAIN_DESCS[i].indexOf('/') >= 0) 
				&& (Ability.DOMAIN_DESCS[i].substring(Ability.DOMAIN_DESCS[i].indexOf('/') + 1).startsWith(qual.toUpperCase())))
				{
					domain = i << 5;
					break;
				}
			}
			if(domain>0)
			{
				domainName=CMStrings.capitalizeAndLower(Ability.DOMAIN_DESCS[domain>>5]);
				msg.append(getQualifiedAbilities(mob,mob,Ability.ACODE_SPELL,domain,"\n\r^H"+domainName+" spells:^? ",shortOnly));
			}
		}
		boolean classesFound=false;
		final int COL_LEN1=CMLib.lister().fixColWidth(3.0,mob);
		final int COL_LEN2=CMLib.lister().fixColWidth(19.0,mob);
		final int COL_LEN3=CMLib.lister().fixColWidth(12.0,mob);
		final int COL_LEN4=CMLib.lister().fixColWidth(13.0,mob);
		if((mob!=null)
		&&(showAll||("CLASSES".startsWith(qual)))
		&&(!CMSecurity.isDisabled(CMSecurity.DisFlag.CLASSES)
		&&(!mob.baseCharStats().getMyRace().classless()))
		)
		{
			int col=0;
			final StringBuffer msg2=new StringBuffer("");
			for(final Enumeration c=CMClass.charClasses();c.hasMoreElements();)
			{
				final CharClass C=(CharClass)c.nextElement();
				final StringBuffer thisLine=new StringBuffer("");
				if((mob.charStats().getCurrentClass()!=C)
				&&(CMLib.login().canChangeToThisClass(mob, C, -1)))
				{
					if((++col)>2)
					{
						thisLine.append("\n\r");
						col=1;
					}
					thisLine.append("^N[^H"+CMStrings.padRight(""+1,COL_LEN1)+"^?] "
					+CMStrings.padRight("^<HELP^>"+C.name()+"^</HELP^>",COL_LEN2)+" "
					+CMStrings.padRight(L("1 train"),(col==2)?COL_LEN3:COL_LEN4));
				}
				if(thisLine.length()>0)
				{
					if(msg2.length()==0)
						msg2.append("\n\r^HClasses:^? \n\r^N[^HLvl^?] Name                Requires     [^HLvl^?] Name                Requires\n\r");
					classesFound=true;
					msg2.append(thisLine);
				}
			}
			msg.append(msg2.toString()+"\n\r");
		}

		if((mob!=null)
		&&(showAll
			||(qual.equalsIgnoreCase("EXPS"))
			||("EXPERTISES".startsWith(qual))))
		{
			final List<ExpertiseDefinition> V=CMLib.expertises().myListableExpertises(mob);
			for(int v=V.size()-1;v>=0;v--)
			{
				if(mob.fetchExpertise(V.get(v).ID())!=null)
					V.remove(v);
			}
			if(V.size()>0)
			{
				if(showAll)
				{
					msg.append(L("\n\r^HExpertises:^?\n\r"));
					ExpertiseLibrary.ExpertiseDefinition def=null;
					int col=0;
					final int COL_LEN=CMLib.lister().fixColWidth(25.0,mob);
					for(int e=0;e<V.size();e++)
					{
						def=V.get(e);
						if(def.name().length()>=COL_LEN)
						{
							if(col>=2)
							{
								msg.append("\n\r");
								col=0;
							}
							msg.append(CMStrings.padRightPreserve("^<HELP^>"+def.name()+"^</HELP^>",COL_LEN));
							final int spaces=(COL_LEN*2)-def.name().length();
							for(int i=0;i<spaces;i++) msg.append(" ");
							col++;
						}
						else
							msg.append(CMStrings.padRight("^<HELP^>"+def.name()+"^</HELP^>",COL_LEN));
						if((++col)>=3)
						{
							msg.append("\n\r");
							col=0;
						}
					}
					if(!msg.toString().endsWith("\n\r"))
						msg.append("\n\r");
				}
				else
				{
					final StringBuffer msg2=new StringBuffer("\n\r^HExpertises:^?\n\rName                          Requires\n\r");
					ExpertiseLibrary.ExpertiseDefinition def=null;
					String req=null;
					String prefix=null;
					final int COL_LEN=CMLib.lister().fixColWidth(30.0,mob);
					for(int v=0;v<V.size();v++)
					{
						def=V.get(v);
						req=CMLib.masking().maskDesc(def.finalRequirements(),true);
						prefix="^<HELP^>"+def.name()+"^</HELP^>";
						if(req.length()<=46)
							msg2.append(CMStrings.padRight(prefix,COL_LEN)+req+"\n\r");
						else
						while(req.length()>0)
						{
							final int x=req.indexOf(".  ");
							if(x<0)
							{
								msg2.append(CMStrings.padRight(prefix,COL_LEN)+req+"\n\r");
								req="";
								break;
							}
							msg2.append(CMStrings.padRight(prefix,COL_LEN)+req.substring(0,x+1)+"\n\r");
							prefix=" ";
							req=req.substring(x+1).trim();
						}
					}
					msg.append(msg2.toString());
				}
			}
		}

		if(mob!=null)
		{
			if(msg.length()==0)
			{
				if(qual.length()>0)
					mob.tell(L("You don't appear to qualify for any '@x1'. Parameters to the QUALIFY command include SKILLS, THIEF, COMMON, SPELLS, PRAYERS, CHANTS, SONGS, EXPERTISES, LANGUAGES, CRAFTING, GATHERING, BUILDING, or NON-CRAFTING.",qual));
				else
					mob.tell(L("You don't appear to qualify for anything! Parameters to the QUALIFY command include SKILLS, THIEF, COMMON, SPELLS, PRAYERS, CHANTS, SONGS, EXPERTISES, LANGUAGES, CRAFTING, GATHERING, BUILDING,, or NON-CRAFTING."));
			}
			else
			if(!mob.isMonster())
			{
				final AbilityComponents.AbilityLimits limits = CMLib.ableComponents().getCommonSkillRemainders(mob);
				if(limits.commonSkills()<0)
					limits.commonSkills(0);
				if(limits.commonSkills() < Integer.MAX_VALUE/2)
					msg.append(L("\n\r^HYou may learn ^w@x1^H more common skills.^N",""+limits.commonSkills()));
				if(limits.craftingSkills()<0)
					limits.craftingSkills(0);
				if(limits.craftingSkills() < Integer.MAX_VALUE/2)
					msg.append(L("\n\r^HYou may learn ^w@x1^H more crafting skills.^N",""+limits.craftingSkills()));
				if(limits.nonCraftingSkills()<0)
					limits.nonCraftingSkills(0);
				if(limits.nonCraftingSkills() < Integer.MAX_VALUE/2)
					msg.append(L("\n\r^HYou may learn ^w@x1^H more non-crafting common skills.^N",""+limits.nonCraftingSkills()));
				
				mob.session().wraplessPrintln(L("^!You now qualify for the following unknown abilities:^?@x1",msg.toString()));
				mob.tell(L("\n\rUse the WILLQUALIFY command to discover what you will qualify for at higher levels."));
				mob.tell(L("\n\rUse the GAIN command with your teacher to gain new skills, spells, and expertises."));
				if(classesFound)
					mob.tell(L("\n\rUse the TRAIN command to train for a new class."));
			}
		}
		return false;
	}

	@Override public boolean canBeOrdered(){return true;}


}