using System;
using System.Collections.Generic;
using System.Text;
using Yamalib.Util;
using Yanesdk.Timer;
using Yanesdk.Draw;
using Yamalib.Scenario;
using Yanesdk.System;

namespace Yamalib.Draw.Effect
{
    /// <summary>
    /// 飾り用クラス
    /// 専用フォーマットによって定義されたシェル動作を画面上に表示します
    /// </summary>
    public class ShellEmulatorDraw
    {
        /// シェル画面情報
        internal class ShellDrawInfo
        {
            public ScenarioParser scenarioParser;
            public RootCounterS textCount;
            public int ox; 	// 描画位置オフセット
            public int oy;
            public int analyzedTag;

            /// コンストラクタ
            public ShellDrawInfo()
            {
                scenarioParser = new ScenarioParser();
                textCount = new RootCounterS();
            }
        }

        #region 定数値

        private const int TYPE_SPEED = 1;	// タイピングスピード
        //	どのタグに該当するかを調べる
        private readonly static string[] tags = new string[]{
			"readstop",	 	// 0 .読み止まり
			"nowait",		// 1 .読み飛ばしSTART
			"/nowait",		// 2 .読み飛ばしEND
			"push"			// 3 .次のプロンプト画面へ
		};

        #endregion

        #region メンバフィールド

        //private PromptCarsor carsor;
        private readonly List<ShellDrawInfo> infos = new List<ShellDrawInfo>();
        private int curInfoIndex;	// 現在表示中のScenarioDrawインデックス
        private GameTimer readWaitTimer;
        private int readwait;
        private bool drawEnd;

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public ShellEmulatorDraw()
        {
            readWaitTimer = new GameTimer();
            ITexture carsortexture = YamalibConst.CreateTexture("img/ending/carsor.png");
            //carsor = new PromptCarsor();
            //carsor.SetTexture( carsortexture );
            readwait = -1;
        }

        /// 毎回呼び出すなりー
        public void OnMove(IScreen screen)
        {
            if (drawEnd) return;

            AnalyzeTag();

            if (readwait == -1)
            {
                infos[curInfoIndex].textCount++;
            }
            else
            {
                if (readWaitTimer.Time >= readwait)
                {
                    readwait = -1;
                }
            }

        }

        /// 毎回できるだけよびだすなりー
        public void OnDraw(IScreen screen)
        {
            if (drawEnd) return;

            ShellDrawInfo shellDrawInfo = infos[curInfoIndex];

            int tx, ty = 0;
            // 描画する矩形情報
            List<ILetterDeta> drawchar = shellDrawInfo.scenarioParser.DrawCharacterData;
            for (int i = 0; i < shellDrawInfo.textCount.Value() && i < drawchar.Count; ++i)
            {
                float size = drawchar[i].Size;

                // 影の描画
                screen.SetColor(0, 0, 0);
                tx = shellDrawInfo.ox + (int)drawchar[i].Pos.X + 2;
                ty = shellDrawInfo.oy + (int)drawchar[i].Pos.Y + 1;

                // 拡大ありで描画
                if (1.0f != size)
                {
                    screen.BltRotate(
                        drawchar[i].ImgObj as ITexture,	// テクスチャ 
                        tx, ty, 	// x,y 位置
                        0, 			// 回転角
                        size, 		// 拡大率
                        0			// 描画ベース位置（左上）
                        );
                }
                else
                {
                    screen.Blt(drawchar[i].ImgObj as ITexture, tx, ty);
                }

                // 本文字の描画
                screen.SetColor(drawchar[i].Color);
                tx = shellDrawInfo.ox + (int)drawchar[i].Pos.X;
                ty = shellDrawInfo.oy + (int)drawchar[i].Pos.Y;

                // 拡大ありで描画
                if (1.0f != size)
                {
                    screen.BltRotate(
                        drawchar[i].ImgObj as ITexture,	// テクスチャ 
                        tx, ty, 	// x,y 位置
                        0, 			// 回転角
                        size, 		// 拡大率
                        0			// 描画ベース位置（左上）
                        );
                }
                else
                {
                    screen.Blt(drawchar[i].ImgObj as ITexture, tx, ty);
                }
            }

            //carsor.SetXY(tx + 8, ty + 3);
            //carsor.OnDraw(screen);

            if (shellDrawInfo.oy + ty > 450)
            {
                shellDrawInfo.oy -= 15;
            }


            if (shellDrawInfo.textCount.IsEnd)
            {
                if (curInfoIndex > 0)
                {
                    curInfoIndex--;
                }
                else
                {
                    drawEnd = true;
                }
            }

            screen.ResetColor();

        }

        /// 表示する画面情報スクリプトファイルを設定する
        public void SetCommands(string[] filenames_, FontLoader fl)
        {

            // 一応前の情報を消去する
            infos.Clear();

            foreach (string filename in filenames_)
            {

                ShellDrawInfo info = new ShellDrawInfo();
                FontRepository fr = new FontRepository(YamalibConst.FONT_REP_TEXTURE_FACTORY);
                fr.SetLoader(fl, 7);
                // ほとんど英数字だからこんくらいあれば...
                fr.Max = (64);
                info.scenarioParser.TextFontRepository = fr;

                ScenarioDrawContext textdrawcontext = new ScenarioDrawContext();
                string strText = YamalibUtility.ReadTextFile(filename);

                textdrawcontext.SetText(strText);
                info.scenarioParser.SetScenarioDrawContext(textdrawcontext);
                info.scenarioParser.UpdateText();
                List<ILetterDeta> drawchar = info.scenarioParser.DrawCharacterData;
                info.textCount.Set(0, drawchar.Count, TYPE_SPEED);
                info.ox = 40;

                infos.Add(info);
            }
        }

        /// 全描画が終了したか
        public bool IsEnd()
        {
            return drawEnd;
        }
        /// <summary>
        /// タグの解析を行います
        /// </summary>
        private void AnalyzeTag()
        {
            ShellDrawInfo shellDrawInfo = infos[curInfoIndex];
            List<ScenarioParser.UnknownTagInfo> tag = shellDrawInfo.scenarioParser.UnknownTags;
            while (shellDrawInfo.analyzedTag < tag.Count && tag[shellDrawInfo.analyzedTag].Pos <= shellDrawInfo.textCount.Value())
            {
                string[] tagStr = tag[shellDrawInfo.analyzedTag].Tag.Split(new char[] { ',' });
                string cc = tagStr[0];
                int found = -1; // not found marker
                for (int i = 0; i < tags.Length; ++i)
                {
                    if (cc == tags[i])
                    {
                        found = i;
                        //Log.print("SED tag %s", tags[found]);
                        break;
                    }
                }

                //	このタグの処理
                switch (found)
                {
                    case 0:		// readstop
                        if (tagStr.Length >= 2)
                        {
                            readwait = Convert.ToInt32(tagStr[1]);
                            readWaitTimer.Reset();
                        }
                        break;

                    case 1:		// nowait
                        shellDrawInfo.textCount.opAssign(tag[shellDrawInfo.analyzedTag + 1].Pos);
                        break;

                    case 2:		// nowaitend
                        break;

                    case 3:		// push
                        curInfoIndex++;
                        break;

                    default:
                        break;
                }

                shellDrawInfo.analyzedTag++;
            }	// while
        }
    }
}
