using System;
using System.Collections.Generic;
using System.Text;
using Yanesdk.System;
using Yamalib.Util;
using System.Diagnostics;
using Yanesdk.Ytl;
using Yanesdk.Movie;
using Yanesdk.Timer;
using Yanesdk.Math;
using Yanesdk.Draw;

namespace Kyojin.Component.Ending
{
    /// <summary>
    /// ムービー再生時の属性データクラス
    /// </summary>
    public class MovieFileInfo : IDisposable
    {
        public static List<MovieFileInfo> CreateFromDefFile(string filename)
        {
            List<MovieFileInfo> result = new List<MovieFileInfo>();
            CSVReader reader = new CSVReader();
            YanesdkResult res = reader.Read(filename);
            if (res == YanesdkResult.NoError)
            {
                foreach (List<string> lineData in reader.CsvData)
                {
                    if (lineData.Count < 6)
                    {
                        continue;
                    }
                    // ファイル名
                    string moviefilename = lineData[0];
                    if (moviefilename == null || string.Empty == moviefilename) continue; // ダメやん

                    MovieFileInfo instance = new MovieFileInfo(moviefilename);

                    // 再生ミリ秒
                    instance.Length = Convert.ToInt32(lineData[1]);
                    // 基本α
                    instance.BaseAlpha = Convert.ToInt32(lineData[2]);
                    // ランダム加算値
                    instance.RandAlpha = Convert.ToInt32(lineData[3]);
                    // インターバル
                    instance.Interval = Convert.ToInt32(lineData[4]);
                    // 評価
                    instance.Rate = Convert.ToInt32(lineData[5]);

                    result.Add(instance);
                }
            }
            return result;
        }

        #region フィールドメンバ

        /** ファイル名 */
        private readonly string m_filename;
        /** 展開の必要が有れば展開 */
        private FileSys.TmpFile m_movieTmpFile;
        /** ミリ秒 */
        private int m_length;
        /** 基本とするα値 */
        private int m_baseAlpha;
        /** ランダムで使用する最大加算値 */
        private int m_randAlpha = 1;
        /** フェードイン・アウトに使用するカウンタ */
        private readonly RootCounterS m_fadeinAlphaCounter;
        private readonly RootCounterS m_fadeoutAlphaCounter;
        /** 頭にいれるインターバル */
        private int m_interval;
        /** 評価値 */
        private long m_rate;


        #endregion


        /** コンストラクタ */
        public MovieFileInfo(string movieFilename)
        {
            m_movieTmpFile = FileSys.GetTmpFile(movieFilename);
            m_filename = m_movieTmpFile.FileName;
            Debug.Assert(m_filename != null);
            //Log.print("MOVIE FILENAME:%s", m_filename);
            m_fadeinAlphaCounter = new RootCounterS();
            m_fadeinAlphaCounter.Set(0, 192, 5);
            m_fadeoutAlphaCounter = new RootCounterS();
            m_fadeoutAlphaCounter.Set(192, 0, 5);
        }

        #region プロパティ

        public string Filename
        {
            get { return m_filename; }
        }

        public int Length
        {
            get { return m_length; }
            set { m_length = value; }
        }

        public int BaseAlpha
        {
            get { return m_baseAlpha; }
            set { m_baseAlpha = value; }
        }

        public int RandAlpha
        {
            get { return m_randAlpha; }
            set { m_randAlpha = value; }
        }

        public RootCounterS FadeinAlphaCounter
        {
            get { return m_fadeinAlphaCounter; }
        }


        public RootCounterS FadeoutAlphaCounter
        {
            get { return m_fadeoutAlphaCounter; }
        }


        public int Interval
        {
            get { return m_interval; }
            set { m_interval = value; }
        }

        public long Rate
        {
            get { return m_rate; }
            set { m_rate = value; }
        }

        #endregion

        #region IDisposable メンバ

        public void Dispose()
        {
            if (m_movieTmpFile != null)
            {
                m_movieTmpFile.Release();
            }
        }

        #endregion
    }

    public class MoviePlayer
    {

        #region フィールドメンバ

        private readonly Rand rand;
        private readonly Movie movie;
        private readonly FixTimer m_intervalTimer;
        private readonly FixTimer m_timer;
        private GlTexture movieTexture;
        private bool m_intervalWait = false;
        private bool m_playing;
        private bool m_fadeout;
        private List<MovieFileInfo> m_playFilenames;
        private int playIndex;

        #endregion

        /** コンストラクタ */
        public MoviePlayer()
        {
            movie = new Movie();
            movieTexture = new GlTexture();
            movieTexture.SetSurface(movie.Surface);
            rand = new Rand();
            rand.Randomize();
            m_intervalTimer = new FixTimer();
            m_intervalTimer.Reset();
            m_timer = new FixTimer();
            m_timer.Reset();
        }

        /** 動作 */
        public void OnMove(IScreen screen)
        {
            try
            {
                m_timer.Update();
                m_intervalTimer.Update();
                if (playIndex >= m_playFilenames.Count)
                {
                    return;
                }

                if (!m_playing)
                {
                    return;
                }

                MovieFileInfo currentMovieInfo = m_playFilenames[playIndex];
                if (m_intervalWait)
                {
                    if (m_intervalTimer.Time >= currentMovieInfo.Interval)
                    {
                        m_playing = false;
                        m_intervalWait = false;
                        Next();
                    }
                }
                else if (m_playing && !movie.IsPlaying)
                {

                    // インターバルとるんか？
                    if (!m_intervalWait && currentMovieInfo.Interval > 0)
                    {
                        m_intervalWait = true;
                        m_intervalTimer.Reset();
                        return;
                    }

                    m_playing = false;
                    Next();
                }
                else
                {
                    currentMovieInfo.FadeinAlphaCounter.Inc();
                    if (!m_fadeout && currentMovieInfo.Length - m_timer.Time < 1500)
                    {
                        m_fadeout = true;
                    }
                    if (m_fadeout)
                    {
                        currentMovieInfo.FadeoutAlphaCounter.Inc();
                    }
                }
            }
            catch
            {
                Console.WriteLine("Movie movie error!");
                Stop();
            }
        }

        /** 描画 */
        public void OnDraw(IScreen screen)
        {
            if (!m_playing || !movie.IsReadyToDraw)
            {
                return;
            }

            if (playIndex >= m_playFilenames.Count)
            {
                return;
            }

            MovieFileInfo currentMovieInfo = m_playFilenames[playIndex];

            if (!currentMovieInfo.FadeinAlphaCounter.IsEnd)
            {
                screen.SetColor(255, 255, 255,
                        currentMovieInfo.FadeinAlphaCounter.Value());
            }
            else if (m_fadeout)
            {
                screen.SetColor(255, 255, 255,
                        currentMovieInfo.FadeoutAlphaCounter.Value());
            }
            else
            {
                screen.SetColor(255, 255, 255,
                        currentMovieInfo.BaseAlpha + rand.GetRand(currentMovieInfo.RandAlpha));
            }

            movie.Draw(movieTexture);
            screen.BlendAddColorAlpha();
            screen.Blt(movieTexture, 0, 0);
        }

        /** プレイファイル名 */
        public void SetPlayFile(List<MovieFileInfo> playFileNames)
        {
            m_playFilenames = playFileNames;
            playIndex = 0;
        }

        /** 再生 */
        public void Play()
        {
            // リストが設定されていない
            if (0 == m_playFilenames.Count)
            {
                return;
            }
            // 全部終了
            if (playIndex >= m_playFilenames.Count)
            {
                return;
            }
            movie.Load(m_playFilenames[playIndex].Filename);
            movieTexture = new GlTexture();
            movieTexture.SetSurface(movie.Surface);
            movie.Play();
            m_timer.Reset();
            m_playing = true;
            m_fadeout = false;
        }

        /** 次へ */
        public void Next()
        {
            if (playIndex < m_playFilenames.Count)
            {
                ++playIndex;
                Play();
            }
        }

        /** 停止 */
        public void Stop()
        {
            movie.Stop();
        }

        /** 解放 */
        public void Release()
        {
            if (movie != null)
            {
                try
                {
                    movie.Release();
                }
                catch
                {

                }
            }
            foreach (MovieFileInfo fileInfo in m_playFilenames)
            {
                fileInfo.Dispose();
            }
        }


    }
}
