using System;
using System.Linq.Expressions;
using System.Reflection;

namespace InABox.Core
{
    public interface ILinkedProperty
    {
        Type Type { get; }
        String Path { get; }
        String Source { get; }
        String Target { get; }
        void Update(object? from, object? to);
        bool Equals(object obj);
    }

    public class LinkedProperty<TLinkedEntity, TEntityLink, TType> : ILinkedProperty
    {
        public Type Type => typeof(TLinkedEntity);
        public String Path { get; }
        public String Source { get; }
        public String Target { get; }
        
        public LinkedProperty(Expression<Func<TLinkedEntity, TEntityLink>> path, 
            Expression<Func<TEntityLink, TType>> source,
            Expression<Func<TLinkedEntity, TType>> target)
        {
            Path = CoreUtils.GetFullPropertyName(path, ".");
            Source = CoreUtils.GetFullPropertyName(source, ".");
            Target = CoreUtils.GetFullPropertyName(target,".");
        }

        public void Update(object? from, object? to)
        {
            if (from != null && to != null)
            {
                var value = CoreUtils.GetPropertyValue(from, Source);
                CoreUtils.SetPropertyValue(to, Target, value);
            }
        }

        public override bool Equals(object obj)
        {
            if (obj is ILinkedProperty src)
            {
                return 
                    String.Equals(src.Path,Path)
                       && String.Equals(src.Source, Source)
                       && String.Equals(src.Target, Target);
            }
            return false;
        }
    }
}