/**********************************************************************************
* Blueprint Reality Inc. CONFIDENTIAL
* 2020 Blueprint Reality Inc.
* All Rights Reserved.
*
* NOTICE:  All information contained herein is, and remains, the property of
* Blueprint Reality Inc. and its suppliers, if any.  The intellectual and
* technical concepts contained herein are proprietary to Blueprint Reality Inc.
* and its suppliers and may be covered by Patents, pending patents, and are
* protected by trade secret or copyright law.
*
* Dissemination of this information or reproduction of this material is strictly
* forbidden unless prior written permission is obtained from Blueprint Reality Inc.
***********************************************************************************/

using System;
using System.Collections;
using System.Runtime.InteropServices;
using UnityEngine;

namespace BlueprintReality.Interprocess.Textures
{
    public class SharedSurfaceProducer : IDisposable
    {
        const string DescFilenameFormat = "MixCast-SharedSurface({0})-Desc";
        const string SurfaceIdFormat = "{0}[{1}]";

        private int producerIndex;
        private SharedSurfaceWriter[] surfaces;

        private ulong writeCount = 0;

        private SharedSurfaceWriter NextWriter
        {
            get
            {
                return surfaces[writeCount % (ulong)surfaces.Length];
            }
        }

        public SharedSurfaceProducer(string chainId, int chainLength)
        {
            producerIndex = CreateSharedSurfaceProducer(chainId, chainLength);

            surfaces = new SharedSurfaceWriter[chainLength];
            for (int i = 0; i < surfaces.Length; i++)
            {
                string frameId = string.Format(SurfaceIdFormat, chainId, i);
                surfaces[i] = new SharedSurfaceWriter(frameId);
            }
        }

        public void Dispose()
        {
            for (int i = 0; i < surfaces.Length; i++)
                surfaces[i].Dispose();
            surfaces = null;

            DisposeSharedSurfaceProducer(producerIndex);
        }

        public bool TryPushFrame(Texture srcTex, ulong syncTime, ulong renderTime, ulong frameIndex, int timeout)
        {
            if (!WaitUntilReadyForNextWrite(timeout))
                return false;

            NextWriter.WriteFrame(srcTex, syncTime, renderTime, frameIndex);
            writeCount++;
            return true;
        }
        public bool PushEndOfFile(int timeout)
        {
            if (!WaitUntilReadyForNextWrite(timeout))
                return false;

            NextWriter.SignalEndOfStream();
            return true;
        }

        private bool WaitUntilReadyForNextWrite(int timeout)
        {
            return NextWriter.WaitUntilReadyForWrite(timeout);
        }

        [DllImport(MixCastInteropPlugin.DllName)]
        private static extern int CreateSharedSurfaceProducer([MarshalAs(UnmanagedType.LPWStr)] string chainId, int chainLength);
        [DllImport(MixCastInteropPlugin.DllName)]
        private static extern int DisposeSharedSurfaceProducer(int producerIndex);
    }
}
