using Google.Protobuf.WellKnownTypes;
using System;
using System.Linq;

namespace XYY.Common.GRPC.Standard
{
    public static class GRPCObjectExtensions
    {
        public static T FromGrpc<T>(this object grpcObj) where T : class
        {
            if (grpcObj == null) throw new ArgumentNullException("参数不能为null");
            T toData = Activator.CreateInstance<T>();
            var properties = toData.GetType().GetProperties().Where(p => p.PropertyType.IsPublic && p.CanWrite).ToList();
            var grcpPs = grpcObj.GetType().GetProperties();
            foreach (var grpcProperties in grcpPs)
            {
                var toPro = properties.FirstOrDefault(x => x.Name.Equals(grpcProperties.Name, StringComparison.OrdinalIgnoreCase));
                var grpcVal = grpcProperties.GetValue(grpcObj, null);
                if (toPro != null)
                {

                    if (toPro.PropertyType == grpcProperties.PropertyType)
                        toPro.SetValue(toData, grpcVal, null);
                    else
                    {
                        if (grpcProperties.PropertyType == typeof(Timestamp) && grpcVal != null)
                        {
                            if (toPro.PropertyType == typeof(DateTime?) || toPro.PropertyType == typeof(DateTime))
                            {
                                Timestamp timeStamp = (Timestamp)grpcVal;
                                toPro.SetValue(toData, timeStamp.ToDateTime().ToLocalTime(), null);
                            }
                        }
                    }
                }
            }
            return toData;
        }

        public static T ToGrpc<T>(this object obj)
        {

            if (obj == null) throw new ArgumentNullException("参数不能为null");
            T toGrpc = Activator.CreateInstance<T>();
            var toRpcProperties = toGrpc.GetType().GetProperties().Where(p => p.PropertyType.IsPublic && p.CanWrite).ToList();
            var objData = obj.GetType().GetProperties();
            foreach (var objPro in objData)
            {
                var toRpcPro = toRpcProperties.FirstOrDefault(x => x.Name.Equals(objPro.Name, StringComparison.OrdinalIgnoreCase));
                var objVal = objPro.GetValue(obj, null);
                if (toRpcPro != null && objVal != null)
                {
                    if (toRpcPro.PropertyType == objPro.PropertyType)
                        toRpcPro.SetValue(toGrpc, objVal, null);
                    else
                    {
                        if (toRpcPro.PropertyType == typeof(Timestamp) && objVal != null)
                        {
                            if (objPro.PropertyType == typeof(DateTime?))
                            {
                                DateTime? datetime = (DateTime?)objVal;
                                DateTime setDateTime = datetime.Value.ToUniversalTime();
                                toRpcPro.SetValue(toGrpc, Timestamp.FromDateTime(setDateTime), null);
                            }
                            else if (objPro.PropertyType == typeof(DateTime))
                            {
                                DateTime datetime = (DateTime)objVal;
                                DateTime setDateTime = datetime.ToUniversalTime();
                                toRpcPro.SetValue(toGrpc, Timestamp.FromDateTime(setDateTime), null);
                            }
                        }                        
                    }
                }
            }
            return toGrpc;
        }
    }
}
