﻿/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Amqp.Types;
using Amqp;
using Apache.NMS;

namespace Apache.NMS.AMQP.Util.Types
{
    internal static class ConversionSupport
    {
        public static Amqp.Types.Map NMSMapToAmqp(IPrimitiveMap nmsmap)
        {
            if(nmsmap == null) return null;
            Amqp.Types.Map result = new Amqp.Types.Map();
            if(nmsmap is Map.AMQP.AMQPValueMap) { return (nmsmap as Map.AMQP.AMQPValueMap).AmqpMap; }
            else
            {
                foreach (string key in nmsmap.Keys)
                {
                    object value = nmsmap[key];

                    if (value is IDictionary)
                    {
                        value = ConversionSupport.MapToAmqp(value as IDictionary);
                    }
                    else if (value is IList)
                    {
                        value = ConversionSupport.ListToAmqp(value as IList);
                    }
                    
                    result[key] = value;
                    //Tracer.InfoFormat("Conversion key : {0}, value : {1}, valueType: {2} nmsValue: {3}, nmsValueType: {4}.", 
                    //    key, value, value.GetType().Name, );
                }
            }
            return result;
        } 

        public static IPrimitiveMap AmqpMapToNMS(Amqp.Types.Map map)
        {
            if (map == null) return null;
            IPrimitiveMap result = new Map.AMQP.AMQPValueMap(map);
            return result;
        }

        public static Amqp.Types.Map MapToAmqp(IDictionary dictionary)
        {
            if (dictionary == null) return null;
            /*if (dictionary is Amqp.Types.Map)
            {
                Amqp.Types.Map DictMap = dictionary as Amqp.Types.Map;
                
                return DictMap.Clone() as Amqp.Types.Map;
            }*/
            Amqp.Types.Map map = new Amqp.Types.Map();
            IEnumerator iterator = dictionary.Keys.GetEnumerator();
            iterator.MoveNext();
            object key = iterator.Current;
            if (key == null) return null;
            object value = null;
            do
            {
                value = dictionary[key];
                if (value != null)
                {
                    Type valtype = value.GetType();
                    if (value is IDictionary)
                    {
                        map[key] = ConversionSupport.MapToAmqp(value as IDictionary);
                    }
                    else if (value is IList)
                    {
                        map[key] = ConversionSupport.ListToAmqp(value as IList);
                    }
                    else if (IsNMSType(value))
                    //else if (valtype.IsPrimitive || value is byte[] || value is String)
                    {
                        map[key] = value;
                    }
                    else
                    {
                        Tracer.InfoFormat("Failed to convert IDictionary[{0}], value{1} to Map value: Invalid Type: {2}", 
                            key, value.ToString(), valtype.Name);
                    }

                }

            }
            while (iterator.MoveNext() && (key = iterator.Current) != null);
            return map;
        }


        public static IDictionary MapToNMS(Amqp.Types.Map map)
        {
            if (map == null) return null;
            
            IDictionary dictionary = new Dictionary<object, object>(map) as IDictionary;

            return dictionary;
        }

        public static IList ListToAmqp(IList ilist)
        {
            if (ilist == null) return null;
            //
            // Special case for Byte[] which has the iList interface, we 
            // don't want to convert Byte[] to a List so just return a copy.
            // Return a copy because it may be added to a List or Dictionary as
            // a reference, which will arrive here, and we want to be sure we have
            // our own copy after return.
            if (ilist is Byte[])
            {
                byte[] copy = new byte[(ilist as Byte[]).Length];
                Array.Copy(ilist as Byte[], 0, copy, 0, (ilist as Byte[]).Length);
                return copy;
            }
            List list = new List();
            foreach(object o in ilist)
            {
                object value = o;
                if(o != null)
                {
                    Type valtype = value.GetType();
                    if (value is IDictionary)
                    {
                        value = ConversionSupport.MapToAmqp(value as IDictionary);
                    }
                    else if (value is IList)
                    {
                        value = ConversionSupport.ListToAmqp(value as IList);
                    }
                    else if (ConversionSupport.IsNMSType(value))
                    //else if (valtype.IsPrimitive || value is byte[] || value is String)
                    {
                        // do nothing
                        // value = value;
                    }
                    else
                    {
                        Tracer.InfoFormat("Failed to convert IList to amqp List value({0}): Invalid Type: {1}", 
                            value.ToString(), valtype.Name);
                    }
                }
                list.Add(value);
            }
            return list;
        }

        public static IList ListToNMS(List list)
        {
            if (list == null) return null;
            IList ilist = new ArrayList(list);
            return ilist;
        }

        public static string ToString(Amqp.Types.Map map)
        {
            if (map == null) return "{}";
            string result = "{";
            bool first = true;
            foreach (object key in map.Keys)
            {
                if (first) result += "\n";
                first = false;
                //
                // handle byte arrays for now
                // add more special handlers as needed.
                //
                if (map[key] is byte[])
                {

                    result += string.Format("key: {0}, len={1}, {2};\n", key.ToString(), (map[key] as byte[]).Length, BitConverter.ToString(map[key] as byte[]).Replace("-", " "));
                }
                else
                {
                    result += "key: " + key.ToString() + ", value: " + map[key].ToString() + ";\n";
                }
            }
            result += "}";
            return result;
        }

        public static string ToString(IPrimitiveMap map)
        {
            if (map == null) return "{}";
            string result = "{";
            bool first = true;
            foreach (string key in map.Keys)
            {
                if (first) result += "\n";
                first = false;
                if (map[key] is byte[])
                {

                    result += string.Format("key: {0}, len={1}, value: {2};\n", key.ToString(), (map[key] as byte[]).Length, BitConverter.ToString(map[key] as byte[]).Replace("-", " "));
                }
                else
                {
                    result += "key: " + key.ToString() + ", value: " + map[key].ToString() + ";\n";
                }
            }
            result += "}";
            return result;
        }

        #region NMS Type Conversion Table

        static ConversionSupport(){
            Dictionary < ConversionKey, ConversionEntry > typeMap = new Dictionary<ConversionKey, ConversionEntry>(NMSTypeConversionSet.Count);
            foreach(ConversionEntry entry in NMSTypeConversionSet)
            {
                typeMap.Add(entry, entry);
            }

            NMSTypeConversionTable = typeMap;
        }

        public enum NMS_TYPE_INDEX
        {
            STRING = 0,
            INT32 = 1,
            UINT32 = 2,
            INT16 = 3,
            UINT16 = 4,
            INT64 = 5,
            UINT64 = 6,
            FLOAT32 = 7,
            FLOAT64 = 8,
            DOUBLE = 8,
            INT8 = 9,
            UINT8 = 10,
            CHAR = 11,
            BOOLEAN = 12,
            BYTE_ARRAY = 13,
            NULL = 14,
            OBJECT = 15,
            UNKOWN
        }

        private static readonly Type[] NMSTypes = { typeof(String),
            typeof(int), typeof(uint),
            typeof(short), typeof(ushort),
            typeof(long), typeof(ulong),
            typeof(float), typeof(double),
            typeof(sbyte), typeof(byte),
            typeof(char), typeof(bool), typeof(byte[]), null, typeof(object) };

        public delegate T ConversionInstance<T, K>(K o);

        private class ConversionKey : IComparable
        {
            private int hash = 0;
            internal static ConversionKey GetKey(Type target, Type Source)
            {

                return new ConversionKey(target, Source);
            }
            protected ConversionKey(Type target, Type source)
            {
                TargetType = target;
                SourceType = source;
                SetHashCode();
            }
            public Type TargetType { get; protected set; }
            public Type SourceType { get; protected set; }

            public int CompareTo(object obj)
            {
                if(obj != null && obj is ConversionKey) { return CompareTo(obj as ConversionKey); }
                return -1;
            }

            protected void SetHashCode()
            {
                long th = TargetType.GetHashCode();
                long sh = SourceType.GetHashCode();
                // Cantor pairing
                hash = (int)((th + sh) * (th + sh + 1) / 2 + sh);
            }

            protected virtual int CompareTo(ConversionKey other)
            {
                return other.GetHashCode() - this.GetHashCode();
            }

            public override bool Equals(object obj)
            {
                if(obj != null && obj is ConversionKey)
                {
                    return this.CompareTo(obj as ConversionKey) == 0;
                }
                else
                {
                    return base.Equals(obj);
                }
            }

            public override int GetHashCode()
            {
                return hash;
            }

            public override string ToString()
            {
                return this.GetType().Name + "| SourceType: " + SourceType.Name + ", TargetType " + TargetType.Name;
            }
        }

        private abstract class ConversionEntry : ConversionKey
        {

            protected ConversionEntry(Type t, Type s) : base(t,s) { }
            
            public abstract object Convert(object o);
        }

        private class ConversionEntry<T, K> : ConversionEntry
        {
            internal ConversionInstance<T, K> ConvertInstance;

            internal ConversionEntry() : base(typeof(T), typeof(K))
            {   
            }


            public override object Convert(object o)
            {
                if (ConvertInstance != null)
                {
                    return ConvertInstance((K)o);
                }
                return null;
            }

            public override string ToString()
            {
                return base.ToString() + ", Convert Instance Delegate : " + ConvertInstance.ToString();
            }
        }

        //public static readonly IReadOnlyDictionary<Type, IReadOnlyDictionary<Type, ConversionInstance<,object>>> NMSTypeConversionTable = new Dictionary<Type, IReadOnlyDictionary<Type, ConversionInstance<?,?>>>
        //{
        /* Type convert to                           Types convert from            */
        /*{ Types[Convert.ToInt32(TYPE_INDEX.STRING)], new Type[]{ typeof(string), typeof(float), typeof(double), typeof(long), typeof(int),typeof(short),typeof(byte),typeof(bool),typeof(char)} },
        { Types[Convert.ToInt32(TYPE_INDEX.DOUBLE)], new Type[]{ typeof(string), typeof(float), typeof(double)} },
        { Types[Convert.ToInt32(TYPE_INDEX.FLOAT32)], new Type[]{ typeof(string), typeof(float)} },
        { Types[Convert.ToInt32(TYPE_INDEX.INT64)], new Type[]{ typeof(string), typeof(long), typeof(int), typeof(short), typeof(byte)} },
        { Types[Convert.ToInt32(TYPE_INDEX.INT32)], new Type[]{ typeof(string), typeof(int), typeof(short), typeof(byte)} },
        { Types[Convert.ToInt32(TYPE_INDEX.INT16)], new Type[]{ typeof(string), typeof(short), typeof(byte)} },
        { Types[Convert.ToInt32(TYPE_INDEX.INT8)], new Type[]{ typeof(string), typeof(byte)} },
        { Types[Convert.ToInt32(TYPE_INDEX.CHAR)], new Type[]{ typeof(char)} },
        { Types[Convert.ToInt32(TYPE_INDEX.BOOLEAN)], new Type[]{ typeof(string), typeof(bool)} },*/

        //};
#if NET40
        private static readonly IDictionary<ConversionKey, ConversionEntry> NMSTypeConversionTable;
#else

        private static readonly IReadOnlyDictionary<ConversionKey, ConversionEntry> NMSTypeConversionTable;
#endif
        private static readonly ISet<ConversionEntry> NMSTypeConversionSet = new HashSet<ConversionEntry>
        {
            // string conversion
            { new ConversionEntry<string, string>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, float>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, double>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, long>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, int>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, short>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, bool>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, char>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, ulong>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, uint>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, ushort>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            { new ConversionEntry<string, byte>{ConvertInstance = ((o) =>{ return Convert.ToString(o); }) } },
            //{new ConversionEntry<string, byte[]>{ConvertInstance = ((o) =>{ throw new InvalidOperationException("Cannot convert string to byte array."); }) } },
            // double conversion
            { new ConversionEntry<double, string>{ConvertInstance = ((o) =>{ return Convert.ToDouble(o); }) } },
            { new ConversionEntry<double, float>{ConvertInstance = ((o) =>{ return Convert.ToDouble(o); }) } },
            { new ConversionEntry<double, double>{ConvertInstance = ((o) =>{ return Convert.ToDouble(o); }) } },
            // float conversion
            { new ConversionEntry<float, string>{ConvertInstance = ((o) =>{ return Convert.ToSingle(o); }) } },
            { new ConversionEntry<float, float>{ConvertInstance = ((o) =>{ return Convert.ToSingle(o); }) } },
            // long conversion
            { new ConversionEntry<long, string>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            { new ConversionEntry<long, long>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            { new ConversionEntry<long, int>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            { new ConversionEntry<long, short>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            { new ConversionEntry<long, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            { new ConversionEntry<long, ulong>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            { new ConversionEntry<long, uint>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            { new ConversionEntry<long, ushort>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            { new ConversionEntry<long, byte>{ConvertInstance = ((o) =>{ return Convert.ToInt64(o); }) } },
            // int conversion
            { new ConversionEntry<int, string>{ConvertInstance = ((o) =>{ return Convert.ToInt32(o); }) } },
            { new ConversionEntry<int, int>{ConvertInstance = ((o) =>{ return Convert.ToInt32(o); }) } },
            { new ConversionEntry<int, short>{ConvertInstance = ((o) =>{ return Convert.ToInt32(o); }) } },
            { new ConversionEntry<int, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToInt32(o); }) } },
            { new ConversionEntry<int, uint>{ConvertInstance = ((o) =>{ return Convert.ToInt32(o); }) } },
            { new ConversionEntry<int, ushort>{ConvertInstance = ((o) =>{ return Convert.ToInt32(o); }) } },
            { new ConversionEntry<int, byte>{ConvertInstance = ((o) =>{ return Convert.ToInt32(o); }) } },
            // short conversion
            { new ConversionEntry<short, string>{ConvertInstance = ((o) =>{ return Convert.ToInt16(o); }) } },
            { new ConversionEntry<short, short>{ConvertInstance = ((o) =>{ return Convert.ToInt16(o); }) } },
            { new ConversionEntry<short, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToInt16(o); }) } },
            { new ConversionEntry<short, ushort>{ConvertInstance = ((o) =>{ return Convert.ToInt16(o); }) } },
            { new ConversionEntry<short, byte>{ConvertInstance = ((o) =>{ return Convert.ToInt16(o); }) } },
            // sbyte conversion
            { new ConversionEntry<sbyte, string>{ConvertInstance = ((o) =>{ return Convert.ToSByte(o); }) } },
            { new ConversionEntry<sbyte, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToSByte(o); }) } },
            { new ConversionEntry<sbyte, byte>{ConvertInstance = ((o) =>{ return Convert.ToSByte(o); }) } },
            // ulong conversion
            { new ConversionEntry<ulong, string>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            { new ConversionEntry<ulong, long>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            { new ConversionEntry<ulong, int>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            { new ConversionEntry<ulong, short>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            { new ConversionEntry<ulong, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            { new ConversionEntry<ulong, ulong>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            { new ConversionEntry<ulong, uint>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            { new ConversionEntry<ulong, ushort>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            { new ConversionEntry<ulong, byte>{ConvertInstance = ((o) =>{ return Convert.ToUInt64(o); }) } },
            // uint conversion
            { new ConversionEntry<uint, string>{ConvertInstance = ((o) =>{ return Convert.ToUInt32(o); }) } },
            { new ConversionEntry<uint, int>{ConvertInstance = ((o) =>{ return Convert.ToUInt32(o); }) } },
            { new ConversionEntry<uint, short>{ConvertInstance = ((o) =>{ return Convert.ToUInt32(o); }) } },
            { new ConversionEntry<uint, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToUInt32(o); }) } },
            { new ConversionEntry<uint, uint>{ConvertInstance = ((o) =>{ return Convert.ToUInt32(o); }) } },
            { new ConversionEntry<uint, ushort>{ConvertInstance = ((o) =>{ return Convert.ToUInt32(o); }) } },
            { new ConversionEntry<uint, byte>{ConvertInstance = ((o) =>{ return Convert.ToUInt32(o); }) } },
            // ushort conversion
            { new ConversionEntry<ushort, string>{ConvertInstance = ((o) =>{ return Convert.ToUInt16(o); }) } },
            { new ConversionEntry<ushort, short>{ConvertInstance = ((o) =>{ return Convert.ToUInt16(o); }) } },
            { new ConversionEntry<ushort, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToUInt16(o); }) } },
            { new ConversionEntry<ushort, ushort>{ConvertInstance = ((o) =>{ return Convert.ToUInt16(o); }) } },
            { new ConversionEntry<ushort, byte>{ConvertInstance = ((o) =>{ return Convert.ToUInt16(o); }) } },
            // byte conversion
            { new ConversionEntry<byte, string>{ConvertInstance = ((o) =>{ return Convert.ToByte(o); }) } },
            { new ConversionEntry<byte, sbyte>{ConvertInstance = ((o) =>{ return Convert.ToByte(o); }) } },
            { new ConversionEntry<byte, byte>{ConvertInstance = ((o) =>{ return Convert.ToByte(o); }) } },
            // boolean conversion
            { new ConversionEntry<bool, string>{ConvertInstance = ((o) =>{ return Convert.ToBoolean(o); }) } },
            { new ConversionEntry<bool, bool>{ConvertInstance = ((o) =>{ return Convert.ToBoolean(o); }) } },
            // char conversion
            { new ConversionEntry<char, char>{ConvertInstance = ((o) =>{ return Convert.ToChar(o); }) } },
        };


        public static Type ForIndex(NMS_TYPE_INDEX index)
        {
            int i = Convert.ToInt32(index);
            
            if(i<0 || i >= (int)NMS_TYPE_INDEX.UNKOWN)
            {
                throw new IndexOutOfRangeException("Unrecognized NMS Type Index " + index);
            }
            else
            {
                return NMSTypes[i];
            }
            
        }

        public static bool IsNMSType(object value)
        {
            bool result = false;
            int index = 0;
            Type t = NMSTypes[index];
            while (t != null && !result)
            {
                result = t.Equals(value.GetType());
                t = NMSTypes[++index];
            }
            return result;
        }

        public static bool CanConvertNMSType<T>(object value)
        {
            ConversionKey key = ConversionKey.GetKey(typeof(T), value.GetType());
            return NMSTypeConversionSet.Contains(key);
        }

        public static T ConvertNMSType<T, S>(S value)
        {
            ConversionKey key = ConversionKey.GetKey(typeof(T), value.GetType());
            ConversionEntry<T, S> converter = (ConversionEntry<T, S>)NMSTypeConversionTable[key];
            if(converter == null)
            {
                throw new NMSTypeConversionException("Cannot convert between type : " + (typeof(T)).Name + ", and type: " + value.GetType().Name);
            }
            return converter.ConvertInstance(value);

        }

        public static T ConvertNMSType<T>(object value)
        {
            ConversionKey key = ConversionKey.GetKey(typeof(T), value.GetType());
            NMSTypeConversionTable.TryGetValue(key, out ConversionEntry converter);
            if (converter == null)
            {
                throw new NMSTypeConversionException("Cannot convert between type : " + (typeof(T)).Name + ", and type: " + value.GetType().Name);
            }
            return (T)converter.Convert(value);
        }

        public class NMSTypeConversionException : MessageFormatException
        {
            public NMSTypeConversionException() : base() { }
            public NMSTypeConversionException(string message) : base(message) { }
        }

#endregion

    }
}
