using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace FormulaEditor
{

    /// <summary>
    /// Acceptor of property operation
    /// </summary>
    public class PropertyAcceptor : IBinaryAcceptor, IBinaryDetector, IOperationDetector
    {

        private Type objectType;
        private string[] propertyNames;
        string propertySeparator;
        private object obj;

        public PropertyAcceptor(Type objectType, string[] propertyNames, string propertySeparator)
        {
            this.propertyNames = propertyNames;
            this.propertySeparator = propertySeparator;
            this.objectType = objectType;
        }

        #region IBinaryAcceptor Members

        public IObjectOperation Accept(object typeA, object typeB)
        {
            if (typeA is object[])
            {
                object[] o = typeA as object[];
                Type type = o[0].GetType();
                object[] ob = typeB as object[];
                string pName = ob[1] as string;
                PropertyInfo[] inform = type.GetProperties();
                //	foreach (PropertyInfo info in inform)
                //	{
                foreach (string propertyName in propertyNames)
                {
                    if (propertyName.Equals(pName))
                    {
                        return new PropertyOperation(o[0], propertyName);
                    }
                }
                //	}
            }
            return null;
        }

        #endregion

        #region IBinaryDetector Members

        public BinaryAssociationDirection AssociationDirection
        {
            get
            {
                return BinaryAssociationDirection.RightLeft;
            }
        }

        public IBinaryAcceptor Detect(MathSymbol s)
        {
            if (s.String.Equals(propertySeparator))
            {
                return this;
            }
            return null;
        }

        #endregion

        #region IOperationDetector Members

        IOperationAcceptor IOperationDetector.Detect(MathSymbol s)
        {
            //PropertyInfo[] inform = objectType.GetProperties();
            //foreach (PropertyInfo info in inform)
            //{
            foreach (string propertyName in propertyNames)
            {
                if (propertyName.Equals(s.String))
                {
                    return new SinglePropertyOperation(this, propertyName);
                }
            }
            //}
            return null;
        }

        #endregion

        #region Specific Members

        public object Object
        {
            get
            {
                return obj;
            }
            set
            {
                if (!value.GetType().Equals(objectType))
                {
                    throw new Exception();
                }
                obj = value;
            }
        }

        public Type ObjectType
        {
            get
            {
                return objectType;
            }
        }

        internal string[] PropertyNames
        {
            get
            {
                return propertyNames;
            }
        }

        #endregion
    }
}
