context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using Server;
  using Server.Items;
  using Server.Gumps;
  using Server.Mobiles;
  using Server.Network;
  using Server.ContextMenus;
  
  namespace Server.Engines.Quests
  {
  	public delegate void QuestCallback();
  
  	public abstract class QuestSystem
  	{
  		public static readonly Type[] QuestTypes = new Type[]
  			{
  				typeof( Doom.TheSummoningQuest ),
  				typeof( Necro.DarkTidesQuest ),
  				typeof( Haven.UzeraanTurmoilQuest ),
  				typeof( Collector.CollectorQuest ),
  				typeof( Hag.WitchApprenticeQuest ),
  				typeof( Naturalist.StudyOfSolenQuest ),
  				typeof( Matriarch.SolenMatriarchQuest ),
  				typeof( Ambitious.AmbitiousQueenQuest ),
  				typeof( Ninja.EminosUndertakingQuest ),
  				typeof( Samurai.HaochisTrialsQuest ),
  				typeof( Zento.TerribleHatchlingsQuest )
  			};
  
  		public abstract object Name{ get; }
  		public abstract object OfferMessage{ get; }
  
  		public abstract int Picture{ get; }
  
  		public abstract bool IsTutorial{ get; }
  		public abstract TimeSpan RestartDelay{ get; }
  
  		public abstract Type[] TypeReferenceTable{ get; }
  
  		private PlayerMobile m_From;
  		private ArrayList m_Objectives;
  		private ArrayList m_Conversations;
  
  		public PlayerMobile From
  		{
  			get{ return m_From; }
  			set{ m_From = value; }
  		}
  
  		public ArrayList Objectives
  		{
  			get{ return m_Objectives; }
  			set{ m_Objectives = value; }
  		}
  
  		public ArrayList Conversations
  		{
  			get{ return m_Conversations; }
  			set{ m_Conversations = value; }
  		}
  
  		private Timer m_Timer;
  
  		public virtual void StartTimer()
  		{
  			if ( m_Timer != null )
  				return;
  
  			m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 0.5 ), TimeSpan.FromSeconds( 0.5 ), new TimerCallback( Slice ) );
  		}
  
  		public virtual void StopTimer()
  		{
  			if ( m_Timer != null )
  				m_Timer.Stop();
  
  			m_Timer = null;
  		}
  
  		public virtual void Slice()
  		{
  			for ( int i = m_Objectives.Count - 1; i >= 0; --i )
  			{
  				QuestObjective obj = (QuestObjective)m_Objectives[i];
  
  				if ( obj.GetTimerEvent() )
  					obj.CheckProgress();
  			}
  		}
  
  		public virtual void OnKill( BaseCreature creature, Container corpse )
  		{
  			for ( int i = m_Objectives.Count - 1; i >= 0; --i )
  			{
  				QuestObjective obj = (QuestObjective)m_Objectives[i];
  
  				if ( obj.GetKillEvent( creature, corpse ) )
  					obj.OnKill( creature, corpse );
  			}
  		}
  
  		public virtual bool IgnoreYoungProtection( Mobile from )
  		{
  			for ( int i = m_Objectives.Count - 1; i >= 0; --i )
  			{
  				QuestObjective obj = (QuestObjective)m_Objectives[i];
  
  				if ( obj.IgnoreYoungProtection( from ) )
  					return true;
  			}
  
  			return false;
  		}
  
  		public QuestSystem( PlayerMobile from )
  		{
  			m_From = from;
  			m_Objectives = new ArrayList();
  			m_Conversations = new ArrayList();
  		}
  
  		public QuestSystem()
  		{
  		}
  
  		public virtual void BaseDeserialize( GenericReader reader )
  		{
  			Type[] referenceTable = this.TypeReferenceTable;
  
  			int version = reader.ReadEncodedInt();
  
  			switch ( version )
  			{
  				case 0:
  				{
  					int count = reader.ReadEncodedInt();
  
  					m_Objectives = new ArrayList( count );
  
  					for ( int i = 0; i < count; ++i )
  					{
  						QuestObjective obj = QuestSerializer.DeserializeObjective( referenceTable, reader );
  
  						if ( obj != null )
  						{
  							obj.System = this;
  							m_Objectives.Add( obj );
  						}
  					}
  
  					count = reader.ReadEncodedInt();
  
  					m_Conversations = new ArrayList( count );
  
  					for ( int i = 0; i < count; ++i )
  					{
  						QuestConversation conv = QuestSerializer.DeserializeConversation( referenceTable, reader );
  
  						if ( conv != null )
  						{
  							conv.System = this;
  							m_Conversations.Add( conv );
  						}
  					}
  
  					break;
  				}
  			}
  
  			ChildDeserialize( reader );
  		}
  
  		public virtual void ChildDeserialize( GenericReader reader )
  		{
  			int version = reader.ReadEncodedInt();
  		}
  
  		public virtual void BaseSerialize( GenericWriter writer )
  		{
  			Type[] referenceTable = this.TypeReferenceTable;
  
  			writer.WriteEncodedInt( (int) 0 ); // version
  
  			writer.WriteEncodedInt( (int) m_Objectives.Count );
  
  			for ( int i = 0; i < m_Objectives.Count; ++i )
  				QuestSerializer.Serialize( referenceTable, (QuestObjective) m_Objectives[i], writer );
  
  			writer.WriteEncodedInt( (int) m_Conversations.Count );
  
  			for ( int i = 0; i < m_Conversations.Count; ++i )
  				QuestSerializer.Serialize( referenceTable, (QuestConversation) m_Conversations[i], writer );
  
  			ChildSerialize( writer );
  		}
  
  		public virtual void ChildSerialize( GenericWriter writer )
  		{
  			writer.WriteEncodedInt( (int) 0 ); // version
  		}
  
  		public bool IsObjectiveInProgress( Type type )
  		{
  			QuestObjective obj = FindObjective( type );
  
  			return ( obj != null && !obj.Completed );
  		}
  
  		public QuestObjective FindObjective( Type type )
  		{
  			for ( int i = m_Objectives.Count - 1; i >= 0; --i )
  			{
  				QuestObjective obj = (QuestObjective)m_Objectives[i];
  
  				if ( obj.GetType() == type )
  					return obj;
  			}
  
  			return null;
  		}
  
  		public virtual void SendOffer()
  		{
  			m_From.SendGump( new QuestOfferGump( this ) );
  		}
  
  		public virtual void GetContextMenuEntries( List<ContextMenuEntry> list )
  		{
  			if ( m_Objectives.Count > 0 )
  				list.Add( new QuestCallbackEntry( 6154, new QuestCallback( ShowQuestLog ) ) ); // View Quest Log
  
  			if ( m_Conversations.Count > 0 )
  				list.Add( new QuestCallbackEntry( 6156, new QuestCallback( ShowQuestConversation ) ) ); // Quest Conversation
  
  			list.Add( new QuestCallbackEntry( 6155, new QuestCallback( BeginCancelQuest ) ) ); // Cancel Quest
  		}
  
  		public virtual void ShowQuestLogUpdated()
  		{
  			m_From.CloseGump( typeof( QuestLogUpdatedGump ) );
  			m_From.SendGump( new QuestLogUpdatedGump( this ) );
  		}
  
  		public virtual void ShowQuestLog()
  		{
  			if ( m_Objectives.Count > 0 )
  			{
  				m_From.CloseGump( typeof( QuestItemInfoGump ) );
  				m_From.CloseGump( typeof( QuestLogUpdatedGump ) );
  				m_From.CloseGump( typeof( QuestObjectivesGump ) );
  
gt: 				m_From.CloseGump( typeof( QuestConversationsGump ) );