context: using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Text;
  using Server;
  using Server.ContextMenus;
  using Server.Network;
  using Server.Gumps;
  using Server.Multis;
  
  namespace Server.Items
  {
  	public class BookPageInfo
  	{
  		private string[] m_Lines;
  
  		public string[] Lines
  		{
  			get
  			{
  				return m_Lines;
  			}
  			set
  			{
  				m_Lines = value;
  			}
  		}
  
  		public BookPageInfo()
  		{
  			m_Lines = new string[0];
  		}
  
  		public BookPageInfo( params string[] lines )
  		{
  			m_Lines = lines;
  		}
  
  		public BookPageInfo( GenericReader reader )
  		{
  			int length = reader.ReadInt();
  
  			m_Lines = new string[length];
  
  			for ( int i = 0; i < m_Lines.Length; ++i )
  				m_Lines[i] = Utility.Intern( reader.ReadString() );
  		}
  
  		public void Serialize( GenericWriter writer )
  		{
  			writer.Write( m_Lines.Length );
  
  			for ( int i = 0; i < m_Lines.Length; ++i )
  				writer.Write( m_Lines[i] );
  		}
  	}
  
  	public class BaseBook : Item, ISecurable
  	{
  		private string m_Title;
  		private string m_Author;
  		private BookPageInfo[] m_Pages;
  		private bool m_Writable;
  		private SecureLevel m_SecureLevel;
  		
  		[CommandProperty( AccessLevel.GameMaster )]
  		public string Title
  		{
  			get { return m_Title; }
  			set { m_Title = value; InvalidateProperties(); }
  		}
  		
  		[CommandProperty( AccessLevel.GameMaster )]
  		public string Author
  		{
  			get { return m_Author; }
  			set { m_Author = value; InvalidateProperties(); }
  		}
  		
  		[CommandProperty( AccessLevel.GameMaster )]
  		public bool Writable
  		{
  			get { return m_Writable; }
  			set { m_Writable = value; }
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public int PagesCount
  		{
  			get { return m_Pages.Length; }
  		}
  
  		public BookPageInfo[] Pages
  		{
  			get { return m_Pages; }
  		}
  
  		[Constructable]
  		public BaseBook( int itemID ) : this( itemID, 20, true )
  		{
  		}
  
  		[Constructable]
  		public BaseBook( int itemID, int pageCount, bool writable ) : this( itemID, null, null, pageCount, writable )
  		{
  		}
  
  		[Constructable]
  		public BaseBook( int itemID, string title, string author, int pageCount, bool writable ) : base( itemID )
  		{
  			m_Title = title;
  			m_Author = author;
  			m_Writable = writable;
  
  			BookContent content = this.DefaultContent;
  
  			if ( content == null )
  			{
  				m_Pages = new BookPageInfo[pageCount];
  
  				for ( int i = 0; i < m_Pages.Length; ++i )
  					m_Pages[i] = new BookPageInfo();
  			}
  			else
  			{
  				m_Pages = content.Copy();
  			}
  		}
  
  		// Intended for defined books only
  		public BaseBook( int itemID, bool writable ) : base( itemID )
  		{
  			m_Writable = writable;
  
  			BookContent content = this.DefaultContent;
  
  			if ( content == null )
  			{
  				m_Pages = new BookPageInfo[0];
  			}
  			else
  			{
  				m_Title = content.Title;
  				m_Author = content.Author;
  				m_Pages = content.Copy();
  			}
  		}
  
  		public virtual BookContent DefaultContent{ get{ return null; } }
  	
  		public BaseBook( Serial serial ) : base( serial )
  		{
  		}
  
  		[Flags]
  		private enum SaveFlags
  		{
  			None		= 0x00,
  			Title		= 0x01,
  			Author		= 0x02,
  			Writable	= 0x04,
  			Content		= 0x08
  		}
  
  		public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
  		{
  			base.GetContextMenuEntries( from, list );
  			SetSecureLevelEntry.AddTo( from, this, list );
  		}
  
  		public override void Serialize( GenericWriter writer )
  		{
  			base.Serialize( writer );
  
  			BookContent content = this.DefaultContent;
  
  			SaveFlags flags = SaveFlags.None;
  
  			if ( m_Title != ( content == null ? null : content.Title ) )
  				flags |= SaveFlags.Title;
  
  			if ( m_Author != ( content == null ? null : content.Author ) )
  				flags |= SaveFlags.Author;
  
  			if ( m_Writable )
  				flags |= SaveFlags.Writable;
  
  			if ( content == null || !content.IsMatch( m_Pages ) )
  				flags |= SaveFlags.Content;
  
  
  
  			writer.Write( (int) 4 ); // version
  
  			writer.Write( (int)m_SecureLevel );
  
  			writer.Write( (byte) flags );
  
  			if ( (flags & SaveFlags.Title) != 0 )
  				writer.Write( m_Title );
  
  			if ( (flags & SaveFlags.Author) != 0 )
  				writer.Write( m_Author );
  
  			if ( (flags & SaveFlags.Content) != 0 )
  			{
  				writer.WriteEncodedInt( m_Pages.Length );
  
  				for ( int i = 0; i < m_Pages.Length; ++i )
  					m_Pages[i].Serialize( writer );
  			}
  		}
  
  		public override void Deserialize( GenericReader reader )
  		{
  			base.Deserialize( reader );
  
  			int version = reader.ReadInt();
  
  			switch ( version )
  			{
  				case 4:
  				{
  					m_SecureLevel = (SecureLevel)reader.ReadInt();
  					goto case 3;
  				}
  				case 3:
  				case 2:
  				{
  					BookContent content = this.DefaultContent;
  
  
gt: 					SaveFlags flags = (SaveFlags) reader.ReadByte();