using System;
using System.Collections.Generic;
using System.Text;
using Yamalib.Util;
using Yanesdk.Draw;
using System.Diagnostics;

namespace Yamalib.Draw.Effect
{
    /// <summary>
    /// 特殊画面フレーム描画を行います
    /// </summary>
    public class ScreenFrame
    {
        #region 定数値

        /** シネマスコープオリジナルアスペクト比 */
        public const float LC_HEIGHT_RATE = 1.0f;
        public const float LC_WIDTH_RATE = 2.35f;
        /** 画面フレームタイプの列挙 */
        public enum SCREEN_TYPE
        {
            NONE, 	// なし
            CHINEMA_SCOPE,	// シネマスコープ 1 * 2.35
        };

        #endregion

        #region フィールドメンバ

        private SCREEN_TYPE screenType;

        private float height_rate;
        private float width_rate;
        private RootCounter counter;
        // エフェクト中か？
        private bool effecting;
        // 停止中か？
        private bool wait;

        // 枠を描画するか
        private int frameSize;

        // スクリーンオープンをマニュアルで行うか？
        private bool openManual;
        private int closeWait;
        private RootCounter waitCounter;

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public ScreenFrame()
        {
            ScreenType = SCREEN_TYPE.CHINEMA_SCOPE;
            SetAspectRate(1.0f, 1.8f);
            counter = new RootCounter();
            waitCounter = new RootCounter();
        }

        /// <summary>
        /// スクリーンタイプを指定
        /// </summary>
        public SCREEN_TYPE ScreenType
        {
            get { return screenType; }
            set { screenType = value; }
        }

        /// <summary>
        /// フレームサイズ
        /// </summary>
        public int FrameSize
        {
            get { return frameSize; }
            set { frameSize = value; }
        }

        /// <summary>
        /// 停止状態かどうか
        /// </summary>
        public bool IsWait
        {
            get { return wait; }
        }

        /// <summary>
        /// 画面のアスペクト比を設定します
        /// </summary>
        /// <param name="h"></param>
        /// <param name="w"></param>
        public void SetAspectRate(float h, float w)
        {
            height_rate = h;
            width_rate = w;
        }

        /// <summary>
        /// 閉じられたスクリーンをオープンする
        /// </summary>
        public void ScreenOpen()
        {
            wait = false;
            openManual = false;
        }

        /// <summary>
        /// Openメッセージを手動で送るか？
        /// メッセージが送られるまで閉じたまま
        /// </summary>
        /// <param name="b"></param>
        public void SetOpenManual(bool b)
        {
            openManual = b;
        }

        /// <summary>
        ///  閉じる開くのスピード
        /// </summary>
        /// <param name="speed"></param>
        /// <param name="closeWait"></param>
        public void SetCloseOpenSpeed(int speed, int closeWait)
        {
            counter.StepValue = speed;
            // 閉じたままの停止時間
            this.closeWait = closeWait;
        }

        /// <summary>
        /// 閉じ開きの描画
        /// </summary>
        /// <param name="screen"></param>
        public void DrawCloseOpen(IScreen screen)
        {
            // 画面サイズの取得
            int width = screen.Width;
            int height = screen.Height;
            // オリジナルカラーの取得
            Color4ub color = YanesdkUtil.GetNowScreenColor(screen);

            screen.SetColor(0, 0, 0, 255);

            if (!effecting)
            {
                // 初期化処理やね
                counter.EndValue = height / 2;
                counter.ReverseFlg = true;
                waitCounter.EndValue = closeWait;

                // 開始位置修正
                if (SCREEN_TYPE.CHINEMA_SCOPE == screenType)
                {
                    float heightRate = height_rate / width_rate;
                    int drawHeight = height - (int)(height * heightRate);
                    counter.opAssign(drawHeight / 2);
                }
                effecting = true;
            }

            if (counter.IsLapAroundI)
            {
            }
            else
            {
                int pos = counter.Value();
                // 上部非描画領域の塗りつぶし
                screen.DrawPolygon(
                    0, 0,
                    width, 0,
                    width, pos,
                    0, pos);

                // 下部非描画領域の塗りつぶし
                screen.DrawPolygon(
                    0, (height - pos),
                    width, (height - pos),
                    width, height,
                    0, height);

                if (wait)
                {
                    if (!openManual)
                    {
                        waitCounter.incS();
                        if (waitCounter.IsLapAround)
                        {
                            wait = false;
                        }
                    }
                }
                else
                {
                    // カウンター増加
                    counter.Inc();
                    if (counter.ReverseFlg && (0 != closeWait || openManual) && !waitCounter.IsLapAround)
                    {
                        wait = true;
                    }
                }
            }
            screen.SetColor(color);
        }

        /// <summary>
        /// 描画処理
        /// </summary>
        /// <param name="screen"></param>
        public void OnPaint(IScreen screen)
        {
            switch (screenType)
            {
                case SCREEN_TYPE.NONE:
                    break;
                case SCREEN_TYPE.CHINEMA_SCOPE:
                    DrawChinemaSope(screen);
                    break;
                default:
                    Debug.Assert(false);
                    break;
            }
        }

        #region 非公開メンバ

        /// <summary>
        /// シネマスコープにします(1 * 2.35)
        /// </summary>
        /// <param name="scren"></param>
        protected void DrawChinemaSope(IScreen screen)
        {
            // 画面サイズの取得
            int width = screen.Width;
            int height = screen.Height;
            float heightRate = height_rate / width_rate;
            int drawHeight = height - (int)(height * heightRate);
            // オリジナルカラーの取得
            Color4ub color = YanesdkUtil.GetNowScreenColor(screen);

            // 黒塗りつぶし
            screen.SetColor(0, 0, 0, 255);

            // 上部非描画領域の塗りつぶし
            screen.DrawPolygon(
                0, 0,
                width, 0,
                width, (drawHeight / 2),
                0, (drawHeight / 2));

            // 下部非描画領域の塗りつぶし
            screen.DrawPolygon(
                0, (height - (drawHeight / 2)),
                width, (height - (drawHeight / 2)),
                width, height,
                0, height);

            if (FrameSize > 0)
            {
                // 白塗りつぶし
                screen.SetColor(255, 255, 255, 255);

                // 上部非描画領域の塗りつぶし
                screen.DrawPolygon(
                    0, (drawHeight / 2) - FrameSize,
                    width, (drawHeight / 2) - FrameSize,
                    width, (drawHeight / 2),
                    0, (drawHeight / 2));

                // 下部非描画領域の塗りつぶし
                screen.DrawPolygon(
                    0, (height - (drawHeight / 2)),
                    width, (height - (drawHeight / 2)),
                    width, (height - (drawHeight / 2)) + FrameSize,
                    0, (height - (drawHeight / 2)) + FrameSize);
            }

            // 色を元に戻す
            screen.SetColor(color);
        }

        #endregion
    }
}
