using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Avi;
using System.Drawing;
using System.Threading;
using TwoCamWPF.Settings;
using InputDevices;

namespace TwoCamWPF.Helpers
{

    class MixerDevice: VideoOutput, IList<IMixerSettings>
    {
        List<IMixerSettings> filters = new List<IMixerSettings>(); //Объекты на кадре
        Size _size;  // Размер кадра
        public Size size
        {
            get {
                lock (sync)
                {
                    return _size;
                }
            }
            set
            {
                lock (sync)
                {
                    _size = value;

                }
            }

        }
        string _Name;
        public string Name
        {
            get
            {
                lock (sync)
                {
                    return _Name;
                }
            }
            set
            {
                lock (sync)
                {
                    _Name = value;
                }
            }

        }
        

        int _frameRate; //Частота обновления микшера.
        public int frameRate
        {
            get
            {
                lock (sync)
                {
                    return _frameRate;
                }
            }
            set
            {
                lock (sync)
                {
                    _frameRate = value;

                }
            }

        }
        
        object sync = new object();
        volatile bool checkRate = false;

        public MixerDevice(Size size, int frameRate)
        {
            this.size = size;
            this.frameRate = frameRate;
        }

       

        void Update()
        {
            if (checkRate)
            {
                return;
            }
            else
            {
                checkRate = true;
            }
            lock (sync)
            {
                Bitmap NewFrame = new Bitmap(size.Width, size.Height);
                foreach (IMixerSettings filter in filters)
                {
                    filter.OnDraw(ref NewFrame);
                }
                DelegatsExecute(NewFrame);
                NewFrame.Dispose();
            }
            checkRate = false;
        }

#region VideoOutput
        public override void StartDevice()
        {
            throw new NotImplementedException();
        }

        public override void StopDevice()
        {
            throw new NotImplementedException();
        }
#endregion

        #region IList
        public IEnumerator<IMixerSettings> GetEnumerator()
        {
            return filters.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return filters.GetEnumerator();
        }

        public int IndexOf(IMixerSettings item)
        {

            lock (sync)
            {
                return filters.IndexOf(item);
            }
        }

        public void Insert(int index, IMixerSettings item)
        {

            lock (sync)
            {
                filters.Insert(index, item);
            }
        }

        public void RemoveAt(int index)
        {
            lock (sync)
            {
                filters.RemoveAt(index);
            }
        }

        public IMixerSettings this[int index]
        {
            get
            {
                lock (sync)
                {
                    return filters[index];
                }
            }
            set
            {
                lock (sync)
                {
                    filters[index] = value;
                }
            }
        }

        public void Add(IMixerSettings item)
        {
            lock (sync)
            {
                filters.Add(item);
            }
        }

        public void Clear()
        {
            lock (sync)
            {
                filters.Clear();
            }
        }

        public bool Contains(IMixerSettings item)
        {
            lock (sync)
            {
                return filters.Contains(item);
            }
        }

        public void CopyTo(IMixerSettings[] array, int arrayIndex)
        {
            lock (sync)
            {
                filters.CopyTo(array, arrayIndex);
            }
        }

        public int Count
        {
            get { return filters.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(IMixerSettings item)
        {
            lock (sync)
            {
                return filters.Remove(item);
            }
        }

        #endregion
    }

    abstract class IMixerSettings: IDisposable
    {
        object sync = new object();
        public void OnDraw(ref Bitmap bmp) {
            lock (sync)
            {
                Draw(ref bmp);
            }
        }
        protected abstract void Draw(ref Bitmap bmp);

        public abstract void Dispose();

    }

    class DeviceFilter : IMixerSettings
    {
        VideoDeviceWatcher device; //Откуда берем
        Rectangle rect;  //Куда пишем
        Bitmap image;
        public DeviceFilter(VideoDeviceWatcher device)
        {
            this.device = device;
            rect = new Rectangle(new Point(0, 0), device.Capability.FrameSize);
            device.Subscribe(this, (bmp) => image = (Bitmap)(bmp.Clone()));
        }


        protected override void Draw(ref Bitmap bmp)
        {
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.DrawImage(image, rect); 
            }
        }


        public override void Dispose()
        {
            device.Unsubscribe(this);
        }
}

    class TextFilter : IMixerSettings
    {
        protected override void Draw(ref Bitmap bmp)
        {

        }
        public override void Dispose()
        {
            throw new NotImplementedException();
        }
    }











}
