/* -LICENSE-START-
** Copyright (c) 2020 Blackmagic Design
** 
** Permission is hereby granted, free of charge, to any person or organization 
** obtaining a copy of the software and accompanying documentation (the 
** "Software") to use, reproduce, display, distribute, sub-license, execute, 
** and transmit the Software, and to prepare derivative works of the Software, 
** and to permit third-parties to whom the Software is furnished to do so, in 
** accordance with:
** 
** (1) if the Software is obtained from Blackmagic Design, the End User License 
** Agreement for the Software Development Kit ("EULA") available at 
** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or
** 
** (2) if the Software is obtained from any third party, such licensing terms 
** as notified by that third party,
** 
** and all subject to the following:
** 
** (3) the copyright notices in the Software and this entire statement, 
** including the above license grant, this restriction and the following 
** disclaimer, must be included in all copies of the Software, in whole or in 
** part, and all derivative works of the Software, unless such copies or 
** derivative works are solely in the form of machine-executable object code 
** generated by a source language processor.
** 
** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 
** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 
** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
** DEALINGS IN THE SOFTWARE.
** 
** A copy of the Software is available free of charge at 
** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.
** 
** -LICENSE-END-
*/

using System;
using System.Runtime.InteropServices;
using DeckLinkAPI;

namespace SignalGenCSharp
{
	class VideoFrame3DExtension : IDeckLinkVideoFrame3DExtensions, ICustomQueryInterface
	{
		private readonly IDeckLinkVideoFrame m_owner;
		private readonly IDeckLinkVideoFrame m_frameRight;

		public class Provider : ICustomQueryInterface
		{
			private readonly WeakReference m_ownerUnmanaged; // Unmanaged pointer. Otherwise reference counting leads to circular references on owner
			private readonly IDeckLinkVideoFrame m_frameRight;

			public Provider(IDeckLinkMutableVideoFrame owner, IDeckLinkVideoFrame right)
            {
				m_ownerUnmanaged = new WeakReference(owner);
				m_frameRight = right;
            }

			CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv)
			{
				if (typeof(IDeckLinkVideoFrame3DExtensions).GUID != iid)
				{
					ppv = IntPtr.Zero;
					return CustomQueryInterfaceResult.Failed;
				}
				IDeckLinkVideoFrame owner = m_ownerUnmanaged.Target as IDeckLinkVideoFrame;
				var ext3D = new VideoFrame3DExtension(owner: owner, right: m_frameRight);
				ppv = Marshal.GetComInterfaceForObject(ext3D, typeof(IDeckLinkVideoFrame3DExtensions), CustomQueryInterfaceMode.Ignore);
				return CustomQueryInterfaceResult.Handled;
			}
		}

		private VideoFrame3DExtension(IDeckLinkVideoFrame owner, IDeckLinkVideoFrame right)
		{
			m_owner = owner;
			m_frameRight = right;
		}

		CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv)
		{
			if (typeof(IDeckLinkVideoFrame3DExtensions).GUID == iid)
			{
				ppv = Marshal.GetComInterfaceForObject(this, typeof(IDeckLinkVideoFrame3DExtensions), CustomQueryInterfaceMode.Ignore);
			}
			else
			{
				// Our owner has all other video frame interfaces
				ppv = Marshal.GetComInterfaceForObject(m_owner, Marshal.GetTypeFromCLSID(iid), CustomQueryInterfaceMode.Ignore);
			}
			return CustomQueryInterfaceResult.Handled;
		}

		_BMDVideo3DPackingFormat IDeckLinkVideoFrame3DExtensions.Get3DPackingFormat() => _BMDVideo3DPackingFormat.bmdVideo3DPackingLeftOnly;

		void IDeckLinkVideoFrame3DExtensions.GetFrameForRightEye(out IDeckLinkVideoFrame rightEyeFrame)
		{
			rightEyeFrame = m_frameRight as IDeckLinkVideoFrame;
		}
	}
}
