using System;
using Quadarax.Foundation.Core.Data.Interface.Entity;
using Quadarax.Foundation.Core.Mapper;

namespace Quadarax.Foundation.Core.Data.Mapper
{
    public class Mapper<TMapper> : Loom where TMapper : class, new()
    {
        /// <summary>
        /// Singleton instance of this class.
        /// </summary>
        public static TMapper Instance => _instance.Value;

        private static readonly Lazy<TMapper> _instance = new Lazy<TMapper>(() => new TMapper());

        #region ------ Constructors ---------------------------------------------------------------

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        public Mapper()
        {
            
        }

        /// <summary>
        /// Defines mappings from a DAO to DTO and vice-versa.
        /// </summary>
        /// <typeparam name="TDao"></typeparam>
        /// <typeparam name="TDto"></typeparam>
        protected void DefineBiDirection<TDao, TDto, TKey>() 
            where TDao : class, IDao<TKey>, new()
            where TDto : class, IDto, new()
            where TKey : IEquatable<TKey>
        {
            Define<TDao, TDto>()
                .PublicProperties()
                .Compile();
            Define<TDto, TDao>()
                .PublicProperties()
                .Compile();
        }

        protected void Define<TDao, TDto>(Action<LoomBuilder<TDao, TDto>> customFromDao)
            where TDao : class, IDao<long>, new()
            where TDto : class, IDto, new()
        {
            // from DAO to DTo
            var builder = Define<TDao, TDto>();
            builder.PublicProperties();
            customFromDao?.Invoke(builder);
            builder.Compile();

        }

        protected void DefineReverse<TDto, TDao>(Action<LoomBuilder<TDto, TDao>> customFromDao)
            where TDao : class, IDao<long>, new()
            where TDto : class, IDto, new()
        {
            // from DTO to DAO
            var builder = Define<TDto, TDao>();
            builder.PublicProperties();
            customFromDao?.Invoke(builder);
            builder.Compile();

        }

        protected void DefineReverse<TDto, TDao>()
            where TDao : class, IDao<long>, new()
            where TDto : class, IDto, new()
        {
            // from DTO to DAO
            var builder = Define<TDto, TDao>();
            builder.PublicProperties();
            builder.Compile();

        }


        #endregion
    }
}
