using InABox.Core;

namespace InABox.IPC
{
public class RPCQueryCommand : IRPCCommand<RPCQueryParameters,RPCQueryResponse> { }
    
    public class RPCQueryDefinition : ISerializeBinary
    {
        public String Key { get; set; }
        public Type Type { get; set; }
        public IFilter? Filter { get; set; }
        public IColumns? Columns { get; set; }
        public ISortOrder? Sort { get; set; }
        
        public void SerializeBinary(CoreBinaryWriter writer)
        {
            writer.Write(Key);
            writer.Write(Type.EntityName());
            writer.Write(Filter != null);
            if (Filter != null)
                Filter.SerializeBinary(writer);
            writer.Write(Columns != null);
            if (Columns != null)
                Columns.SerializeBinary(writer);
            writer.Write(Sort != null);
            if (Sort != null)
                Sort.SerializeBinary(writer);
        }

        public void DeserializeBinary(CoreBinaryReader reader)
        {
            Key = reader.ReadString();
            var type = reader.ReadString();
            Type = CoreUtils.GetEntity(type);
            if (reader.ReadBoolean())
            {
                var filtertype = typeof(Filter<>).MakeGenericType(Type);
                Filter = Activator.CreateInstance(filtertype) as IFilter;
                Filter?.DeserializeBinary(reader);
            }
            if (reader.ReadBoolean())
            {
                var columnstype = typeof(Columns<>).MakeGenericType(Type);
                Columns = Activator.CreateInstance(columnstype) as IColumns;
                Columns?.DeserializeBinary(reader);
            }
            if (reader.ReadBoolean())
            {
                var sorttype = typeof(SortOrder<>).MakeGenericType(Type);
                Sort = Activator.CreateInstance(sorttype) as ISortOrder;
                Sort?.DeserializeBinary(reader);
            }
            
        }
    }
    
    public class RPCQueryParameters : ISerializeBinary
    {
        public RPCQueryDefinition[] Queries { get; set; }

        public void SerializeBinary(CoreBinaryWriter writer)
        {
            writer.WriteBinaryValue(typeof(RPCQueryDefinition[]), Queries);
        }

        public void DeserializeBinary(CoreBinaryReader reader)
        {
            Queries = reader.ReadBinaryValue(typeof(RPCQueryDefinition[])) as RPCQueryDefinition[] ?? new RPCQueryDefinition[] {};
        }
    }

    public class RPCQueryTable : ISerializeBinary
    {
        
        public String Key { get; set; }
        public CoreTable Table { get; set; }
        
        public void SerializeBinary(CoreBinaryWriter writer)
        {
            writer.Write(Key);
            Table.SerializeBinary(writer);
        }

        public void DeserializeBinary(CoreBinaryReader reader)
        {
            Key = reader.ReadString();
            Table = new CoreTable();
            Table.DeserializeBinary(reader);
        }
    }
    
    public class RPCQueryResponse : ISerializeBinary
    {
        public RPCQueryTable[] Tables { get; set;}
        
        public void SerializeBinary(CoreBinaryWriter writer)
        {
            writer.WriteBinaryValue(typeof(RPCQueryTable[]), Tables);
        }

        public void DeserializeBinary(CoreBinaryReader reader)
        {
            Tables = reader.ReadBinaryValue(typeof(RPCQueryTable[])) as RPCQueryTable[] ?? new RPCQueryTable[] { };
        }
    }
}