using System;
using System.Collections.Generic;
using System.Text;
using Yanesdk.GUIParts;
using Yamalib.GUI;
using Yanesdk.Draw;
using Yanesdk.Input;
using Yamalib.Input;

namespace Yamalib.GUI
{
    public class FocusableGUIParam
    {
        private IKeyInput key;
        private IMouseInput mouse;


        public FocusableGUIParam(IMouseInput mouse, IKeyInput key)
        {
            this.mouse = mouse;
            this.key = key;
        }

        /// <summary>
        /// 拡張マウスに対応させる
        /// </summary>
        public IMouseInput Mouse
        {
            get { return mouse; }
            set { mouse = value; }
        }

        /// <summary>
        /// キー対応させる
        /// </summary>
        public IKeyInput Key
        {
            get { return key; }
            set { key = value; }
        }
    }

    /// <summary>
    /// フォーカス可能なTexutreButtonの実装
    /// </summary>
    public class FocusableTextureButton : TextureButton, FocusableTextureGUI
    {
        private string defFile;
        private bool isDefFileRelative = false;
        private IMouseInput mouse = null;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="defFile"></param>
        public FocusableTextureButton(string defFile)
            : base(defFile)
        {
            this.defFile = defFile;
            isDefFileRelative = false;
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="defFile"></param>
        /// <param name="isDefFileRelative"></param>
        public FocusableTextureButton(string defFile, bool isDefFileRelative)
            : base(defFile, isDefFileRelative)
        {
            this.defFile = defFile;
            this.isDefFileRelative = isDefFileRelative;
        }

        TextureLoader loader;

        public override void OnInit(ControlContext cc)
        {
            loader = cc.SmartTextureLoader.LoadDefFile(defFile, isDefFileRelative);
            FocusableGUIParam param = cc.Param as FocusableGUIParam;
            if (null != param)
            {
                mouse = param.Mouse;
            }
        }


        private int width, height;
        private bool isOnDown;
        //　前フレームの結果
        private bool lastIsDown;
        private bool lastIsHover;

        /// <summary>
        /// IMouseInputで動作を行うようにしてある
        /// </summary>
        /// <param name="scr"></param>
        /// <param name="cc"></param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        public override void OnPaint(IScreen scr, ControlContext cc, int x, int y)
        {
            if (!Visible) return;

            if (width == 0 || height == 0)
            {
                ITexture t0 = loader.GetTexture(LoaderOffset);
                // ボタンサイズを取得しておき、これをマウスの判定矩形として利用する
                if (t0 != null)
                {
                    width = (int)t0.Width;
                    height = (int)t0.Height;
                }
            }

            int mx, my;
            mouse.GetPos(out mx, out my);
            bool isHover =
                (x <= mx) && (mx < x + width) &&
                (y <= my) && (my < y + height);

            bool isDown = mouse.IsPress(MouseInput.Button.Left);
            // 前フレームで、
            // isHover状態でかつisDown
            // 今回のフレームで
            // isHover状態かつ、!isDown
            // ならば、ボタンが押されたとしてボタンイベント発生。

            isOnDown = false;
            if (Enable)
            {
                if (lastIsHover && lastIsDown && isHover && !isDown)
                {
                    if (OnClick != null)
                    {
                        OnClick(scr, cc);
                    }
                    isOnDown = true;
                }
                if (lastIsHover && !lastIsDown && isHover && isDown)
                {
                    if (OnDown != null)
                        OnDown(scr, cc);
                }
            }
            lastIsDown = isDown;
            lastIsHover = isHover;

            int pattern;
            if (!Enable)
                pattern = 3;
            else if (!isHover)
                pattern = 0;
            else if (isDown)
                pattern = 1;
            else
                pattern = 2;

            ITexture tex = loader.GetTexture(pattern + LoaderOffset);
            if (tex != null)
            {
                if (Color != null)
                {
                    scr.SetColor(Color.Value);
                    scr.Blt(tex, x, y);
                    scr.ResetColor();
                }
                else
                {
                    scr.Blt(tex, x, y);
                }
            }
        }

        /// <summary>
        /// オーバーライドできないなら new するしかない
        /// FocusableTextureButton でアクセスするしかない...
        /// </summary>
        public new bool IsHover
        {
            get { return lastIsHover; }
        }

        /// <summary>
        /// こいつもオーバーライド出来ないので new する
        /// FocusableTextureButton でアクセスして...
        /// </summary>
        /// <remarks>
        /// Enable == falseならば常にfalseを返す
        /// </remarks>
        public new bool IsDown
        {
            get { return isOnDown && Enable; }
        }

        #region FocusableTextureGUI メンバ

        public void Focus(ControlContext controlContext, int x, int y)
        {
            if (width == 0 || height == 0)
            {
                ITexture t0 = loader.GetTexture(LoaderOffset);
                // ボタンサイズを取得しておき、これをマウスの判定矩形として利用する
                if (t0 != null)
                {
                    width = (int)t0.Width;
                    height = (int)t0.Height;
                }
            }
            mouse.SetPos(x + width / 2, y + height / 2);
        }

        #endregion
    }
}
