using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CookComputing.XmlRpc;

namespace BTS.Trac
{
    /// <summary>
    ///Wiki APIs
    /// </summary>
    public class Wiki
    {
        /// <summary>
        /// Wiki 属性
        /// </summary>
        class WikiAttributes
        {
            public const string NAME = "name";                  // ページ名称
            public const string VERSION = "version";            // バージョン
            public const string LASTMODIFIED = "lastModified";  // 最終更新日
            public const string AUTHOR = "author";              // 変更者
            public const string COMMENT = "comment";            // コメント
        }

        /// <summary>
        /// 属性
        /// </summary>
        XmlRpcAttributes Attributes = new XmlRpcAttributes();

        /// <summary>
        /// ページ名称
        /// </summary>
        public string Name
        {
            get
            {
                return Attributes.Get<string>( WikiAttributes.NAME );
            }

            private set
            {
                Attributes.Set( WikiAttributes.NAME, value );
            }
        }

        /// <summary>
        /// バージョン
        /// </summary>
        public int Version
        {
            get
            {
                return Attributes.Get<int>( WikiAttributes.VERSION );
            }

            private set
            {
                Attributes.Set( WikiAttributes.VERSION, value );
            }
        }

        /// <summary>
        /// 最終変更日
        /// </summary>
        public DateTime LastModified
        {
            get
            {
                return Attributes.Get<DateTime>( WikiAttributes.LASTMODIFIED );
            }

            private set
            {
                Attributes.Set( WikiAttributes.LASTMODIFIED, value );
            }
        }

        /// <summary>
        /// 変更者
        /// </summary>
        public string Author
        {
            get
            {
                return Attributes.Get<string>( WikiAttributes.AUTHOR );
            }

            set
            {
                Attributes.Set( WikiAttributes.AUTHOR, value );
            }
        }

        /// <summary>
        /// コメント
        /// </summary>
        public string Comment
        {
            get
            {
                return Attributes.Get<string>( WikiAttributes.COMMENT );
            }

            set
            {
                Attributes.Set( WikiAttributes.COMMENT, value );
            }
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Wiki()
        {
            Name = "";
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="name">ページ名称</param>
        public Wiki( string name )
        {
            Name = name;
            GetInfo();
        }

        public XmlRpcStruct GetRecentChanges( DateTime since )
        {
            return null;
        }

        /// <summary>
        /// 指定されたページの内容を Wiki 記法で取得する
        /// </summary>
        /// <returns>ページの内容</returns>
        public string Get()
        {
            return Trac.Rpc.wikiGetPage( Name );
        }

        /// <summary>
        /// 指定されたページの内容を HTML で取得
        /// </summary>
        /// <returns></returns>
        public string GetHTML()
        {
            return Trac.Rpc.wikiGetPageHTML( Name );
        }

        /// <summary>
        /// 指定されたページの情報を取得する
        /// </summary>
        public void GetInfo()
        {
            Attributes.value = Trac.Rpc.wikiGetPageInfo( Name );
        }

        /// <summary>
        /// ページを更新する
        /// </summary>
        /// <param name="content">新しいコンテンツ</param>
        public void Update( string content )
        {
            Create( Name, content );
        }

        /// <summary>
        /// 新しいページを作成する
        /// </summary>
        /// <param name="pagename">作成するページ名称</param>
        /// <param name="content">作成するコンテンツ</param>
        public void Create( string pagename, string content )
        {
            Name = pagename;
            bool ret = Trac.Rpc.wikiPutPage( pagename, content, Attributes.value );
            if ( !ret ) {
                throw new Exception( "wikiPutPage" );
            }
        }

        /// <summary>
        /// ページを削除する
        /// </summary>
        public void Delete()
        {
            Delete( Name );
        }

        /// <summary>
        /// 添付ファイルの一覧を取得する
        /// </summary>
        /// <returns>添付ファイルの一覧</returns>
        public List<WikiAttachment> ListAttachments()
        {
            string[] paths = Trac.Rpc.wikiListAttachments( Name );

            List<WikiAttachment> attachments = new List<WikiAttachment>( paths.Length );
            foreach( string path in paths ) {
                attachments.Add( new WikiAttachment( this, path ) );
            }

            return attachments;
        }

        #region 静的メソッド
        /// <summary>
        /// RPC バージョンを取得する
        /// </summary>
        /// <returns>RPC バージョン番号</returns>
        public static int GetRpcVersionSupported()
        {
            return Trac.Rpc.wikiGetRpcVersionSupported();
        }

        /// <summary>
        /// すべてのページ名を取得
        /// </summary>
        /// <returns>ページ名の一覧</returns>
        public static string[] GetAllPages()
        {
            return Trac.Rpc.wikiGetAllPages();
        }

        /// <summary>
        /// Wiki 記法のページを HTML に変換する
        /// </summary>
        /// <param name="text">変換する Wiki 記法のテキスト</param>
        /// <returns>HTML のテキスト</returns>
        /// <note>GetPageHTML の HTML とは違った</note>
        public static string WikiToHtml( string text )
        {
            return Trac.Rpc.wikiWikiToHtml( text );
        }

        /// <summary>
        /// 指定されたページを削除する
        /// </summary>
        /// <param name="name">削除するページの名称</param>
        public static void Delete( string name )
        {
            bool ret = Trac.Rpc.wikiDeletePage( name );
            if ( !ret ) {
                throw new Exception( "wikiDeletePage" );
            }
        }
        #endregion
    }
}
