/*
		public static int GetSpecialNumber(Style style)
		{
			if (style.SpecialType == Style.eSpecialType.Effect)
			{
				Spell spell = SkillBase.GetSpellById(style.SpecialValue);
				if (spell != null)
					return spell.ClientEffect;
			}
			return 0;
		}

		public static int GetSpecialValue(Style style)
		{
			switch(style.SpecialType)
			{
				case Style.eSpecialType.ExtendedRange:
					return 128; // Extended Range für Reaver style
				case Style.eSpecialType.Taunt:
					return style.SpecialValue;
			}
			return 0;
		}*/

		
		/*public static int GetOpeningResult(Style style,GameClient clt)
		{
			switch(StyleProcessor.ResolveAttackResult(style,clt.Player.PlayerCharacter.Class))
			{
				case GameLiving.eAttackResult.Any:
					return (int)Style.eAttackResult.Any;
				case GameLiving.eAttackResult.Missed:
					return (int) Style.eAttackResult.Miss;
				case GameLiving.eAttackResult.Parried:
					return (int)Style.eAttackResult.Parry;
				case GameLiving.eAttackResult.Evaded:
					return (int)Style.eAttackResult.Evade;
				case GameLiving.eAttackResult.Blocked:
					return (int)Style.eAttackResult.Block;
				case GameLiving.eAttackResult.Fumbled:
					return (int)Style.eAttackResult.Fumble;
				case GameLiving.eAttackResult.HitStyle:
					return (int)Style.eAttackResult.Style;
				case GameLiving.eAttackResult.HitUnstyled:
					return (int)Style.eAttackResult.Hit;
			}
			return 0;
		}*/
		/*
		public static string GetOpeningStyle(Style style)
		{
			if (style.OpeningRequirementValue > 0)
			{
				Style style2 = SkillBase.GetStyleByID(style.OpeningRequirementValue);
				if (style2!=null)
					return style2.Name;
				return "";
			}
			return "";
		}*/

		#endregion

		/// <summary>
		/// Delve the realm abilities for v1.110+ clients
		/// </summary>
		/// <param name="clt"></param>
		/// <param name="id"></param>
		/// <returns></returns>
        public static string DelveRealmAbility(GameClient clt, int id)
        {
			Skill ra = clt.Player.GetAllUsableSkills().Where(e => e.Item1.InternalID == id && e.Item1 is Ability).Select(e => e.Item1).FirstOrDefault();
			
			if (ra == null)
			{
				ra = SkillBase.GetAbilityByInternalID(id);
			}
			
			MiniDelveWriter dw = new MiniDelveWriter("RealmAbility");
			dw.AddKeyValuePair("Index",  unchecked((short)id));
			
            if (ra is RealmAbility)
            {
           		((RealmAbility)ra).AddDelve(ref dw);
            }
            else if (ra != null)
            {
                dw.AddKeyValuePair("Name", ra.Name);
            }
            else
            {
           		dw.AddKeyValuePair("Name", "(not found)");
            }
            
            return dw.ToString();
        }
		public static string DelveStyle(GameClient clt, int id)
        {
			Tuple<Skill,Skill> sk = clt.Player.GetAllUsableSkills().Where(e => e.Item1.InternalID == id && e.Item1 is Style).FirstOrDefault();
        	
			Style style = null;
        	if(sk == null || sk.Item1 == null)
        	{
            	style = SkillBase.GetStyleByInternalID(id);
        	}
        	else if (sk.Item1 is Style)
        	{
        		style = (Style)sk.Item1;
        	}

            MiniDelveWriter dw = new MiniDelveWriter("Style");
            dw.AddKeyValuePair("Index",  unchecked((short)id));

            if (style != null)
            {
                // Not implemented:
                // (Style (FollowupStyle "Sapphire Slash")(LevelBonus "2")(OpeningDamage "16")(Skill "1")(Expires "1343375647"))
                // (Style (Fingerprint "1746652963")(FollowupStyle "Thigh Cut")(Hidden "1")OpeningDamage "55")(Skill "118")(SpecialNumber "1511")(SpecialType "1")(Expires "1342381240"))
				// Skill = GetSpecToInternalIndex
				// find opening style, and follow up !!
				
				IEnumerable<Style> styles = clt.Player.GetSpecList().SelectMany(e => e.PretendStylesForLiving(clt.Player, clt.Player.MaxLevel));
				
				// Is a followup
				if (style.OpeningRequirementType == Style.eOpening.Offensive && style.AttackResultRequirement == Style.eAttackResultRequirement.Style)
				{
					Style st = styles.Where(s => s.ID == style.OpeningRequirementValue).FirstOrDefault();
					if (st != null)
					{
						// opening style should be only one.
						dw.AddKeyValuePair("OpeningStyle", st.Name);
					}
				}
				
				// Has Followup ?
				foreach (Style stl in styles.Where(s => (s.OpeningRequirementType == Style.eOpening.Offensive && s.AttackResultRequirement == Style.eAttackResultRequirement.Style && s.OpeningRequirementValue == style.ID)))
				{
					// we found the style that needs this one for opening.
					dw.AppendKeyValuePair("FollowupStyle", stl.Name);
				}
				
				dw.AddKeyValuePair("Name", style.Name);
				dw.AddKeyValuePair("Icon", style.Icon);
				dw.AddKeyValuePair("Level", style.Level);
				dw.AddKeyValuePair("Fatigue", style.EnduranceCost);
				//.Value("SpecialType", (int)style.SpecialType, style.SpecialType != 0)
				//.Value("SpecialNumber", GetSpecialNumber(style), GetSpecialNumber(style)!=0)
				if (style.BonusToDefense != 0)
					dw.AddKeyValuePair("DefensiveMod", style.BonusToDefense);
				if (style.BonusToHit != 0)
					dw.AddKeyValuePair("AttackMod", style.BonusToHit);
				dw.AddKeyValuePair("OpeningType", (int)style.OpeningRequirementType);
				if (style.OpeningRequirementType == Style.eOpening.Positional)
					dw.AddKeyValuePair("OpeningNumber", style.OpeningRequirementValue);				
				//.Value("OpeningResult",GetOpeningResult(style,clt),GetOpeningResult(style,clt)>0)
				//.Value("OpeningStyle",GetOpeningStyle(style),(Style.eAttackResult)GetOpeningResult(style,clt) == Style.eAttackResult.Style)
				if (style.WeaponTypeRequirement > 0)
					dw.AddKeyValuePair("Weapon", style.GetRequiredWeaponName());
				if (style.StealthRequirement)
					dw.AddKeyValuePair("Hidden", "1");
				//.Value("TwoHandedIcon", 10, style.TwoHandAnimation > 0)
				//.Value("Skill",43)
				if (style.GrowthRate>0)
					dw.AddKeyValuePair("OpeningDamage",style.GrowthRate*100);
				//.Value("SpecialValue", GetSpecialValue(style),GetSpecialValue(style)!=0)
				//.Value("FollowupStyle",style.DelveFollowUpStyles,!string.IsNullOrEmpty(style.DelveFollowUpStyles))
            }
            else
            {
                dw.AddKeyValuePair("Name", "(not found)");
            }
            
            return dw.ToString();
        }
		/// <summary>
		/// Delve Info for Songs (V1.110+)
		/// </summary>
		/// <param name="clt">Client</param>
		/// <param name="id">SpellID</param>
		/// <returns></returns>
		public static string DelveSong(GameClient clt, int id)
		{
			MiniDelveWriter dw = new MiniDelveWriter("Song");
			dw.AddKeyValuePair("Index", unchecked((short)id));
			
			Spell spell = SkillBase.GetSpellByTooltipID((ushort)id);
		
			ISpellHandler spellHandler = ScriptMgr.CreateSpellHandler(clt.Player, spell, SkillBase.GetSpellLine(GlobalSpellsLines.Reserved_Spells));
			
			if (spellHandler != null)
			{
				dw.AddKeyValuePair("effect", spellHandler.Spell.InternalID);
				dw.AddKeyValuePair("Name", spellHandler.Spell.Name);
				return dw.ToString();
			}

			// not found
			dw.AddKeyValuePair("Name", "(not found)");
			return dw.ToString();
		}
		/// <summary>
		/// Delve Info for Spells (V1.110+)
		/// </summary>
		/// <param name="clt">Client</param>
		/// <param name="id">SpellID</param>
		/// <returns></returns>
        public static string DelveSpell(GameClient clt, int id)
        {
            MiniDelveWriter dw = new MiniDelveWriter("Spell");
			
            Spell spell = SkillBase.GetSpellByTooltipID((ushort)id);
        	// Spell object are mostly "DB" Object, we can't subclass this object easily, but Spellhandler create subclass using "SpellType"
        	// We better rely on the handler to delve it correctly ! using reserved spellline as we can't guess it ! player can delve other object effect !
			ISpellHandler spellHandler = ScriptMgr.CreateSpellHandler(clt.Player, spell, SkillBase.GetSpellLine(GlobalSpellsLines.Reserved_Spells));
			
			if (spellHandler != null)
			{
				spellHandler.TooltipDelve(ref dw, id);
				return dw.ToString();
			}

        	// not found
        	dw.AddKeyValuePair("Index", unchecked((short)id));
        	dw.AddKeyValuePair("Name", "(not found)");
            return dw.ToString();
        }
        /** General info @ v1.110:
         *  - Examples can be found at http://dl.dropbox.com/u/48908369/delve.txt
         *  - 'Expires' can be left out
         *  - No idea what 'Fingerprint' does
         **/

        public static string DelveAbility(GameClient clt, int id)
        { /* or skill */

        	Skill sk = clt.Player.GetAllUsableSkills().Where(e => e.Item1.InternalID == id).OrderBy(e => e.Item1 is Ability ? 0 : 1).Select(e => e.Item1).FirstOrDefault();
        	
        	if(sk == null)
        		sk = SkillBase.GetAbilityByInternalID(id);
        	
        	if(sk == null)
        		sk = SkillBase.GetSpecializationByInternalID(id);
        	
        	MiniDelveWriter dw = new MiniDelveWriter(sk is Ability ? "Ability" : "Skill");

        	dw.AddKeyValuePair("Index", unchecked((short)id));

            if (sk != null) 
            {
                dw.AddKeyValuePair("Name", sk.Name);
            }
            else
            {
            	dw.AddKeyValuePair("Name", "(not found)");
            }
            
            return dw.ToString();
        }