using System;
using System.Xml;

namespace Anycmd.Xacml
{
    /// <summary>
    /// ËùÓÐxacmlÔªËØµÄ»ùÀàÐÍ¡£
    /// </summary>
    public abstract class XacmlElement
    {
        #region Private members

        private readonly XacmlVersion _schemaVersion;
        private readonly XacmlSchema _schema;

        #endregion

        #region Constructor

        /// <summary>
        /// Ä¬ÈÏ³õÊ¼»¯Æ÷¡£
        /// </summary>
        /// <param name="schema">ÓÃÀ´ÑéÖ¤ÎÄµµµÄÃ¶¾Ù</param>
        /// <param name="schemaVersion">ÓÃÓÚ¼ÓÔØxacmlÔªËØµÄÄ£Ê½µÄ°æ±¾</param>
        protected XacmlElement(XacmlSchema schema, XacmlVersion schemaVersion)
        {
            _schema = schema;
            _schemaVersion = schemaVersion;
        }

        /// <summary>
        /// ¿Õ¹¹ÔìÆ÷¡£
        /// </summary>
        protected XacmlElement()
        {
        }
        #endregion

        #region Public properties

        /// <summary>
        /// ÓÃÀ´ÑéÖ¤ÎÄµµµÄÃ¶¾Ù¡£
        /// </summary>
        public XacmlVersion SchemaVersion
        {
            get { return _schemaVersion; }
        }

        /// <summary>
        /// ¶¨ÒåÁËxacmlÔªËØµÄÄ£Ê½£¨Schema£©¡£
        /// </summary>
        public XacmlSchema Schema
        {
            get { return _schema; }
        }

        /// <summary>
        /// ²é¿´µ±Ç°ÊµÀýÊÇ·ñÊÇÖ»¶Á°æ±¾¡£
        /// </summary>
        public abstract bool IsReadOnly
        {
            get;
        }

        #endregion

        #region Protected methods

        /// <summary>
        /// ¸ù¾Ý¸ø¶¨µÄ°æ±¾ºÅÑéÖ¤¸ø¶¨µÄÄ£Ê½¡£
        /// </summary>
        /// <param name="reader">ÓÃÓÚ¶ÁÈ¡ÃüÃû¿Õ¼ä</param>
        /// <param name="version">ÓÃÓÚÑéÖ¤°æ±¾ºÅ</param>
        /// <returns><c>true</c>, Èç¹ûÃüÃû¿Õ¼äÕýÈ·</returns>
        protected bool ValidateSchema(XmlReader reader, XacmlVersion version)
        {
            if (reader == null) throw new ArgumentNullException("reader");
            switch (_schema)
            {
                case XacmlSchema.Policy:
                    switch (version)
                    {
                        case XacmlVersion.Version10:
                        case XacmlVersion.Version11:
                            return (reader.NamespaceURI == Consts.Schema1.Namespaces.Policy);
                        case XacmlVersion.Version20:
                            return (reader.NamespaceURI == Consts.Schema2.Namespaces.Policy);
                        default:
                            throw new EvaluationException("ÒâÍâµÄ°æ±¾ºÅ" + version);
                    }
                    break;
                case XacmlSchema.Context:
                    switch (version)
                    {
                        case XacmlVersion.Version10:
                        case XacmlVersion.Version11:
                            return (reader.NamespaceURI == Consts.Schema1.Namespaces.Context);
                        case XacmlVersion.Version20:
                            return (reader.NamespaceURI == Consts.Schema2.Namespaces.Context);
                        default:
                            throw new EvaluationException("ÒâÍâµÄ°æ±¾ºÅ" + version);
                    }
                    break;
                default:
                    throw new EvaluationException("ÒâÍâµÄÄ£Ê½" + _schema);
            }
        }

        #endregion
    }
}
