using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Threading;
namespace DevComponents.DotNetBar.Animation
{
    internal class Storyline : Component
    {
        #region Events
        #endregion
        #region Constructor
        #endregion
        #region Implementation
        private bool _IsDisposed = false;
        /// 
        /// Returns whether Storyline is disposed.
        /// 
        public bool IsDisposed
        {
            get
            {
                return _IsDisposed;
            }
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                BackgroundWorker worker = _Worker;
                if (worker != null)
                {
                    worker.CancelAsync();
                    worker.Dispose();
                    _Worker = null;
                }
            }
            _IsDisposed = true;
            base.Dispose(disposing);
        }
        private List _Animations = new List();
        /// 
        /// Gets the list of animations to run using this storyline.
        /// 
        public List Animations
        {
            get
            {
                return _Animations;
            }
        }
        private BackgroundWorker _Worker = null;
        /// 
        /// Runs all animations from Animations list.
        /// 
        public void Run()
        {
            if (_Worker != null)
                throw new InvalidOperationException("Storyline is already running animations");
            _Worker = new BackgroundWorker();
            _Worker.WorkerReportsProgress = true;
            _Worker.WorkerSupportsCancellation = true;
            _Worker.DoWork += new DoWorkEventHandler(WorkerDoWork);
            _Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
            _Worker.RunWorkerAsync();
        }
        void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (_RepeatStoryTimes > 0)
            {
                if (_Worker == null)
                {
                    _RepeatStoryTimes = 0;
                    return;
                }
                _RepeatStoryTimes--;
                _Worker.RunWorkerAsync();
            }
            else
            {
                if (_Worker != null)
                    _Worker.Dispose();
                _Worker = null;
                if (_AutoDispose && !_IsDisposed)
                    this.Dispose();
            }
        }
        void WorkerDoWork(object sender, DoWorkEventArgs e)
        {
            int count = _Animations.Count;
            for (int i = 0; i < count; i++)
            {
                if (e.Cancel) return;
                _Animations[i].Start();
                while (!_Animations[i].IsCompleted)
                {
                    try
                    {
                        using (
                                        System.Threading.ManualResetEvent wait =
                                            new System.Threading.ManualResetEvent(false))
                            wait.WaitOne(50);
                        //Thread.Sleep(50);
                    }
                    catch 
                    {
                        _Animations[i].Stop();
                        return;
                    }
                    if (e.Cancel)
                    {
                        _Animations[i].Stop();
                        return;
                    }
                }
            }
        }
        private int _RepeatStoryTimes = 0;
        /// 
        /// Gets or sets number of times storyline is repeated. Default value is 0 which indicates that storyline is run only once meaning not repeated.
        /// 
        public int RepeatStoryTimes
        {
            get { return _RepeatStoryTimes; }
            set { _RepeatStoryTimes = value; }
        }
        private bool _AutoDispose = false;
        /// 
        /// Gets or sets whether storyline is auto-disposed when finished.
        /// 
        public bool AutoDispose
        {
            get { return _AutoDispose; }
            set
            {
                _AutoDispose = value;
            }
        }
        #endregion
    }
}