using System;
using System.Collections.Generic;

namespace InABox.DigitalMatter
{
    public interface IDMObject
    {
        void Decode(byte[] data);
        byte[] EncodeArray();
    }

    public abstract class DMObject : IDMObject
    {

        public void Decode(IDMReadBuffer readBuffer)
        {
            BeforeDecode(readBuffer);
            DoDecode(readBuffer);
            AfterDecode(readBuffer);
        }
        public void Decode(List<byte> data) => Decode(new DMListReadBuffer(data));

        public void Decode(byte[] data) => Decode(new DMArrayReadBuffer(data));

        public byte[] EncodeArray() => EncodeList().ToArray();

        public void Encode(IDMWriteBuffer buffer)
        {
            BeforeEncode(buffer);
            DoEncode(buffer);
            AfterEncode(buffer);
        }

        public List<byte> EncodeList()
        {
            var buffer = new DMListWriteBuffer(new List<byte>());
            Encode(buffer);
            return buffer.Buffer;
        }

        protected uint SecondsSince2013UTC()
        {
            var epoch = new DateTime(2013, 1, 1);
            var utc = DateTime.Now.ToUniversalTime();
            var elapsed = utc - epoch;
            return (uint)elapsed.TotalSeconds;
        }

        public DateTime TimeStampToDateTime(uint timestamp)
        {
            return new DateTime(2013, 1, 1).AddSeconds(timestamp).ToLocalTime();
        }

        protected virtual void BeforeEncode(IDMWriteBuffer buffer)
        {
        }

        protected abstract void DoEncode(IDMWriteBuffer buffer);

        protected virtual void AfterEncode(IDMWriteBuffer buffer)
        {
        }

        protected virtual void BeforeDecode(IDMReadBuffer buffer)
        {
        }

        protected abstract void DoDecode(IDMReadBuffer buffer);

        protected virtual void AfterDecode(IDMReadBuffer buffer)
        {
        }
    }
}