using System;
using System.Runtime.InteropServices;

namespace Nativ {
    public static class NativeMethods {
        // Initialize the AVIFile library
        [DllImport("avifil32.dll")]
        internal static extern void AVIFileInit();

        // Exit the AVIFile library 
        [DllImport("avifil32.dll")]
        internal static extern void AVIFileExit();

        // Open an AVI file
        [DllImport("avifil32.dll",CharSet = CharSet.Unicode)]
        internal static extern int AVIFileOpen(
            out IntPtr ppfile,
            String szFile,
            OpenFileMode mode,
            IntPtr pclsidHandler);

        // Release an open AVI stream
        [DllImport("avifil32.dll")]
        internal static extern int AVIFileRelease(
            IntPtr pfile);

        // Get address of a stream interface that is associated
        // with a specified AVI file
        [DllImport("avifil32.dll")]
        internal static extern int AVIFileGetStream(
            IntPtr pfile,
            out IntPtr ppavi,
            int fccType,
            int lParam);

        // Create a new stream in an existing file and creates an interface to the new stream
        [DllImport("avifil32.dll")]
        internal static extern int AVIFileCreateStream(
            IntPtr pfile,
            out IntPtr ppavi,
            ref AVISTREAMINFO psi);

        // Release an open AVI stream
        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamRelease(
            IntPtr pavi);

        // Set the format of a stream at the specified position
        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamSetFormat(
            IntPtr pavi,
            int lPos,
            ref BITMAPINFOHEADER lpFormat,
            int cbFormat);
        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamSetFormat(
            IntPtr pavi,
            int lPos,
            ref WAVEFORMATEX lpFormat,
            int cbFormat);

        // Get the starting sample number for the stream
        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamStart(
            IntPtr pavi);

        // Get the length of the stream
        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamLength(
            IntPtr pavi);

        // Obtain stream header information
        [DllImport("avifil32.dll",CharSet = CharSet.Unicode)]
        internal static extern int AVIStreamInfo(
            IntPtr pavi,
            ref AVISTREAMINFO psi,
            int lSize);

        // Prepare to decompress video frames from the specified video stream
        [DllImport("avifil32.dll")]
        internal static extern IntPtr AVIStreamGetFrameOpen(
            IntPtr pavi,
            ref BITMAPINFOHEADER lpbiWanted);
        [DllImport("avifil32.dll")]
        internal static extern IntPtr AVIStreamGetFrameOpen(
            IntPtr pavi,
            int lpbiWanted);

        // Releases resources used to decompress video frames
        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamGetFrameClose(
            IntPtr pget);

        // Return the address of a decompressed video frame
        [DllImport("avifil32.dll")]
        internal static extern IntPtr AVIStreamGetFrame(
            IntPtr pget,
            int lPos);

        // Write data to a stream
        [DllImport("avifil32.dll")]
        public static extern int AVIStreamWrite(
            IntPtr streamHandler,
            int start,
            int samples,
            IntPtr buffer,
            int bufferSize,
            int flags,
            IntPtr samplesWritten,
            IntPtr bytesWritten);

        // Retrieve the save options for a file and returns them in a buffer
        [DllImport("avifil32.dll")]
        internal static extern int AVISaveOptions(
            IntPtr hwnd,
            int flags,
            int streams,
            [In,MarshalAs(UnmanagedType.LPArray,SizeParamIndex = 0)] IntPtr[] ppavi,
            [In,MarshalAs(UnmanagedType.LPArray,SizeParamIndex = 0)] IntPtr[] plpOptions);

        // Free the resources allocated by the AVISaveOptions function
        [DllImport("avifil32.dll")]
        internal static extern int AVISaveOptionsFree(
            int streams,
            [In,MarshalAs(UnmanagedType.LPArray,SizeParamIndex = 0)] IntPtr[] plpOptions);

        // Create a compressed stream from an uncompressed stream and a
        // compression filter, and returns the address of a pointer to
        // the compressed stream
        [DllImport("avifil32.dll")]
        internal static extern int AVIMakeCompressedStream(
            out IntPtr ppsCompressed,
            IntPtr psSource,
            ref AVICOMPRESSOPTIONS lpOptions,
            IntPtr pclsidHandler);

        // --- memory functions

        // memcpy - copy a block of memery
        [DllImport("ntdll.dll")]
        internal static extern IntPtr memcpy(
            IntPtr dst,
            IntPtr src,
            int count);
        //[DllImport("ntdll.dll")]
        //internal static extern int memcpy(
        //    int dst,
        //    int src,
        //    int count);

        /// <summary>
        /// Copy a block of memory.
        /// </summary>
        /// 
        /// <param name="dst">Destination pointer.</param>
        /// <param name="src">Source pointer.</param>
        /// <param name="count">Memory block's length to copy.</param>
        /// 
        /// <returns>Return's the value of <b>dst</b> - pointer to destination.</returns>
        /// 
        [DllImport("ntdll.dll", CallingConvention = CallingConvention.Cdecl)]
        internal static extern int memcpy(
            int dst,
            int src,
            int count);

        // --- structures

        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamReadFormat(
            IntPtr aviStream,Int32 lPos,
            ref BITMAPINFOHEADER lpFormat,ref Int32 cbFormat
            );
         [DllImport("avifil32.dll")]
       
        internal static extern int AVIStreamReadFormat(
                  IntPtr aviStream,Int32 lPos,
                  ref WAVEFORMATEX lpFormat,ref Int32 cbFormat
                  );


        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamRead(IntPtr pavi,int lStart,int lSamples,IntPtr lpBuffer,int cbBuffer,out int plBytes,out int plSamples);

        [DllImport("avifil32.dll")]
        internal static extern uint AVIFileInfo(IntPtr pfile,out AVIFILEINFO pfi,int lSize);
        internal static int mmioFOURCC(string str) {
            return (
                ((int)(byte)(str[0])) |
                ((int)(byte)(str[1]) << 8) |
                ((int)(byte)(str[2]) << 16) |
                ((int)(byte)(str[3]) << 24));
        }
        // Inverse of mmioFOURCC 
        internal static string decode_mmioFOURCC(int code) {
            char[] chs = new char[4];

            for (int i = 0; i < 4; i++) {
                chs[i] = (char)(byte)((code >> (i << 3)) & 0xFF);
                if (!char.IsLetterOrDigit(chs[i]))
                    chs[i] = ' ';
            }
            return new string(chs);
        }
        [DllImport("avifil32.dll")]
        internal static extern int AVIStreamBeginStreaming(
          IntPtr pavi,
          int lStart,
          int lEnd,
          int lRate
            );

        internal static int AVISaveOptions(IntPtr stream, ref AVICOMPRESSOPTIONS options)
        {
            IntPtr[] streams = new IntPtr[1];
            IntPtr[] infPtrs = new IntPtr[1];
            IntPtr mem;
            int ret;

            // alloc unmanaged memory
            mem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(AVICOMPRESSOPTIONS)));

            // copy from managed structure to unmanaged memory
            Marshal.StructureToPtr(options, mem, false);

            streams[0] = stream;
            infPtrs[0] = mem;

            // show dialog with a list of available compresors and configuration
            ret = AVISaveOptions(IntPtr.Zero, 0, 1, streams, infPtrs);

            // copy from unmanaged memory to managed structure
            options = (AVICOMPRESSOPTIONS)Marshal.PtrToStructure(mem, typeof(AVICOMPRESSOPTIONS));

            // free AVI compression options
            AVISaveOptionsFree(1, infPtrs);

            // clear it, because the information already freed by AVISaveOptionsFree
            options.cbFormat = 0;
            options.cbParms = 0;

            // free unmanaged memory
            Marshal.FreeHGlobal(mem);

            return ret;
        }





            [DllImport("gdi32")]
            public static extern int DeleteObject(IntPtr hObject);
 

    }
    [Serializable]
    public class VideoException:Exception  {
        /// <summary>
        /// Initializes a new instance of the <see cref="VideoException"/> class.
        /// </summary>
        /// 
        /// <param name="message">Exception's message.</param>
        /// 
        public VideoException(string message) :
            base(message) { }
    }
}
