using System;
using System.Collections.Generic;
using System.Text;
using Yanesdk.Math;
using Yanesdk.Draw;

namespace Yamalib.Draw.Effect
{
    /// <summary>
    /// テクスチャを水平線上でズレズレで表示させるクラス
    /// </summary>
    public class TextureLineNoise
    {
        #region フィールドメンバ

        private readonly Rand rand;
        private ITexture t;
        private readonly List<int> slant = new List<int>();	//!< ずれ幅
        private int posx;
        private int posy;
        private int randWidth;
        private int effectingCounter;
        private int effectingTime;
        private int nowEffectingTime;
        private bool bEffectingTimeRand = true;
        private bool bInterval;
        private int intervalCounter;
        private int interval;
        private int nowInterval;
        private bool intervalRand = true;
        private int tWidth = 0;
        private int tHeight = 0;

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public TextureLineNoise()
        {
            rand = new Rand();
            rand.Randomize();
            randWidth = 4;
            interval = 100;
            effectingTime = 60;
            nowEffectingTime = rand.GetRand(effectingTime);
        }

        /// <summary>
        /// フェクト描画するテクスチャー
        /// </summary>
        public ITexture Texture
        {
            get { return t; }
            set
            {
                t = value;
                tWidth = (int)t.Width;
                tHeight = (int)t.Height;
            }
        }

        /// <summary>
        /// 描画位置の設定
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        public void SetXY(int x, int y)
        {
            posx = x;
            posy = y;
        }

        /// <summary>
        /// 水平乱れの間の平均フレーム数
        /// </summary>
        public int Interval
        {
            get { return nowInterval; }
            set { nowInterval = value; }
        }

        /// <summary>
        /// 水平乱れ間の正常状態維持フレーム数をランダムにする
        /// </summary>
        public bool UseIntervalRand
        {
            get { return intervalRand; }
            set { intervalRand = value; }
        }

        /// <summary>
        /// 水平乱れが持続する平均フレーム数
        /// </summary>
        public int EffectingTime
        {
            get { return effectingTime; }
            set { effectingTime = value; }
        }

        /// <summary>
        /// 水平乱れが持続する時間を乱数にする
        /// </summary>
        public bool UseEffectingTimeRand
        {
            get { return bEffectingTimeRand; }
            set { bEffectingTimeRand = value; }
        }

        /// <summary>
        /// 乱数がとりうる幅
        /// </summary>
        public int RandWidth
        {
            get { return randWidth; }
            set { randWidth = value; }
        }

        /// <summary>
        /// 描画処理
        /// </summary>
        /// <param name="screen"></param>
        public void OnPaint(IScreen screen)
        {
            if (t == null) return;

            if (bInterval)
            {
                intervalCounter++;
                if (nowInterval <= intervalCounter)
                {
                    intervalCounter = 0;
                    bInterval = false;
                    nowInterval = rand.GetRand(interval);
                }
            }

            if (bInterval)
            {
                screen.Blt(t, posx, posy);
            }
            else
            {
                Rect rc = new Rect();
                for (int i = 0; i < tHeight; ++i)
                {
                    rc.Top = i;
                    rc.Bottom = i + 1;
                    rc.Left = 0;
                    rc.Right = tWidth;

                    int offsetx = rand.GetRand(randWidth) - randWidth / 2;
                    screen.Blt(t, posx + offsetx, posy + i, rc);

                }
            }

            if (!bInterval)
            {
                effectingCounter++;
                if (nowEffectingTime <= effectingCounter)
                {
                    effectingCounter = 0;
                    bInterval = true;
                    nowEffectingTime = rand.GetRand(effectingTime);
                }
            }
        }
    }
}
