using System;
using System.IO;

namespace skyscraper5.Skyscraper.IO.LibDvbV5
{
    public class LibDvbV5OpenDescriptor : IDisposable
    {
        public IntPtr Pointer { get; private set; }

        internal LibDvbV5OpenDescriptor(IntPtr pointer)
        {
            Pointer = pointer;
        }

        protected bool Equals(LibDvbV5OpenDescriptor other)
        {
            return Pointer.Equals(other.Pointer);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((LibDvbV5OpenDescriptor)obj);
        }

        public override int GetHashCode()
        {
            return Pointer.GetHashCode();
        }

        public override string ToString()
        {
            return String.Format("{0} 0x{X:16}", nameof(LibDvbV5DeviceList), Pointer.ToInt64());
        }

        public void Dispose()
        {
            LibDvbV5.DvbDevClose(Pointer);
            Pointer = IntPtr.Zero;
        }

        public void SetBufferSize(int bufferSize)
        {
            if (LibDvbV5.DvbDeviceSetBufferSize(Pointer, bufferSize) != 0)
            {
                throw new IOException("failed to set buffer size");
            }
        }

        public void DemuxSetPesFilter(int pid, DemuxerPesType pesType)
        {
            if (LibDvbV5.DvbDeviceDemuxerSetPesFilter(Pointer, pid, pesType, DemuxerOutput.DMX_OUT_TS_TAP, 0) != 0)
            {
                throw new IOException("setPesFilter failed");
            }
        }

        public int Read(byte[] buf, int count)
        {
            int result = LibDvbV5.DvbDeviceRead(Pointer, buf, count);
            if (result == -1)
                throw new IOException("read failed");
            return result;
        }
    }
}