using NewTek;
using NewTek.NDI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace VIZ.Framework.Common
{
    /// <summary>
    /// 查找NDI流任务
    /// </summary>
    public class NDIStreamFindStreamTask : NDIStreamTaskBase
    {
        /// <summary>
        /// 查找NDI流任务
        /// </summary>
        /// <param name="stream">NDI流</param>
        public NDIStreamFindStreamTask(NDIStream stream) : base(stream)
        {

        }

        /// <summary>
        /// 任务名称
        /// </summary>
        public override NDIStreamTaskNames Name => NDIStreamTaskNames.FIND_STREAM;

        /// <summary>
        /// the size of an NDIlib.source_t, for pointer offsets
        /// </summary>
        private readonly int SOURCE_SIZE_IN_BYTES = Marshal.SizeOf(typeof(NDIlib.source_t));

        /// <summary>
        /// 执行
        /// </summary>
        protected override void Execute()
        {
            while (this.IsStarted)
            {
                this._Execute();
            }
        }

        /// <summary>
        /// 执行
        /// </summary>
        private void _Execute()
        {
            if (!NDIlib.find_wait_for_sources(this.Stream.FindInstancePtr, 500))
                return;

            lock (this.Stream.StreamInfos)
            {
                this.Stream.StreamInfos.Clear();
            }

            uint numSources = 0;
            IntPtr sourcesPtr = NDIlib.find_get_current_sources(this.Stream.FindInstancePtr, ref numSources);

            for (int i = 0; i < numSources; i++)
            {
                // 连续的数据结构
                IntPtr p = IntPtr.Add(sourcesPtr, (i * SOURCE_SIZE_IN_BYTES));

                // 指针转化为 NDIlib.source_t 数据结构 
                NDIlib.source_t src = (NDIlib.source_t)Marshal.PtrToStructure(p, typeof(NDIlib.source_t));

                // NDI流名称
                string ndiName = UTF.Utf8ToString(src.p_ndi_name);

                // 添加NDI流信息
                NDIStreamInfo info = new NDIStreamInfo();
                info.FullName = ndiName;
                info.Machine = ndiName.Split(new char[] { ' ' }, 2)[0];
                info.Name = ndiName.Substring(ndiName.IndexOf(' ') + 1);
                info.Source = src;

                lock (this.Stream.StreamInfos)
                {
                    this.Stream.StreamInfos.Add(info);
                }
            }

            // 如果当前没有正在处理的流信息那么切换为当前RemoteSenderName指定的流信息
            if (this.Stream.CurrentRemoteSenderSource == null)
            {
                this.Stream.ChangeRemoteSenderName(this.Stream.RemoteSenderName);
            }
        }
    }
}
