using System;
using System.Linq.Expressions;
using System.Runtime.Serialization;

namespace InABox.Core
{
    [Serializable]
    public abstract class SerializableExpression<T> : ISerializable // where T : Entity
    {
        protected SerializableExpression(SerializationInfo info, StreamingContext context)
        {
            var value = (string)info.GetValue("Expression", typeof(string));
            Expression = CoreUtils.StringToExpression(value);
            Deserialize(info, context);
        }

        public SerializableExpression(Expression expression)
        {
            Expression = expression;
        }

        public SerializableExpression(Expression<Func<T, object?>> expression)
        {
            Expression = CoreUtils.ExtractMemberExpression(expression);
        }

        public SerializableExpression()
        {
            Expression = Expression.Parameter(typeof(T), "x");
        }

        public SerializableExpression(string property)
        {
            Expression = CoreUtils.GetMemberExpression(typeof(T), property);
        }

        public SerializableExpression(SerializableExpression<T> other)
        {
            Expression = other.Expression;
        }

        public Expression Expression { get; set; }

        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Expression", CoreUtils.ExpressionToString(typeof(T), Expression, true));
            Serialize(info, context);
        }

        public abstract void Serialize(SerializationInfo info, StreamingContext context);

        public abstract void Deserialize(SerializationInfo info, StreamingContext context);

        public override string ToString()
        {
            return Expression != null ? CoreUtils.ExpressionToString(typeof(T), Expression, true) : "";
        }
    }
}