#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2010 the Open Toolkit library.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to 
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#endregion

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Text;

using OpenTK.Input;


namespace OpenTK.Platform.Windows
{
    // Input driver for legacy (pre XP) Windows platforms.
    // Supports a single mouse and keyboard through WM_MOUSE* and WM_KEY* events.
    // Supports multiple joysticks through WinMM.
    sealed class WMInput : 
#if !ASYNC_INPUT
        WinInputBase,
#else
        IInputDriver2,
#endif
        IMouseDriver2, IKeyboardDriver2, IGamePadDriver
    {
        #region Fields

        readonly WinMMJoystick gamepad_driver = new WinMMJoystick();
        KeyboardState keyboard = new KeyboardState();
        MouseState mouse = new MouseState();

        readonly WinKeyMap KeyMap = new WinKeyMap();

        #endregion

        #region Constructor

        public WMInput()
            : base()
        {
            Debug.WriteLine("Using WMInput.");
        }

        #endregion

        #region Private Members
#if ASYNC_INPUT
        void UpdateKeyboard()
        {
            for (int i = 0; i < 256; i++)
            {
                VirtualKeys key = (VirtualKeys)i;
                bool pressed = (Functions.GetAsyncKeyState(key) >> 8) != 0;
                if (KeyMap.ContainsKey(key))
                {
                        keyboard[KeyMap[key]] = pressed;
                }
            }
        }

        void UpdateMouse()
        {
            POINT p = new POINT();
            Functions.GetCursorPos(ref p);
            // Note: we cannot poll the mouse wheel
            mouse[MouseButton.Left] = (Functions.GetAsyncKeyState(VirtualKeys.LBUTTON) >> 8) != 0;
            mouse[MouseButton.Middle] = (Functions.GetAsyncKeyState(VirtualKeys.RBUTTON) >> 8) != 0;
            mouse[MouseButton.Right] = (Functions.GetAsyncKeyState(VirtualKeys.MBUTTON) >> 8) != 0;
            mouse[MouseButton.Button1] = (Functions.GetAsyncKeyState(VirtualKeys.XBUTTON1) >> 8) != 0;
            mouse[MouseButton.Button2] = (Functions.GetAsyncKeyState(VirtualKeys.XBUTTON2) >> 8) != 0;
        }
#endif
        #endregion

        #region Protected Members

        protected override IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
        {
            return base.WindowProcedure(handle, message, wParam, lParam);
        }

        protected override void CreateDrivers()
        {
            //keyboard.IsConnected = true;
            //Native.KeyDown += delegate(object sender, KeyboardKeyEventArgs e)
            //{
            //    keyboard.EnableBit((int)e.Key);
            //};
            //Native.KeyUp += delegate(object sender, KeyboardKeyEventArgs e)
            //{
            //    keyboard.DisableBit((int)e.Key);
            //};

            //mouse.IsConnected = false;
            // Todo: implement and hook INativeWindow.Mouse* events.
            //Native.MouseMove += delegate(object sender, MouseMoveEventArgs e)
            //{
            //};
        }

        #endregion

        #region IInputDriver2 Members

        public override IKeyboardDriver2 KeyboardDriver
        {
            get { return this; }
        }

        public override IMouseDriver2 MouseDriver
        {
            get { return this; }
        }

        public override IGamePadDriver GamePadDriver
        {
            get { return this; }
        }

        #endregion

        #region IMouseDriver2 Members

        public MouseState GetState()
        {
            return mouse;
        }

        public MouseState GetState(int index)
        {
            if (index == 0)
                return mouse;
            else
                return new MouseState();
        }

        #endregion

        #region IKeyboardDriver2 Members

        KeyboardState IKeyboardDriver2.GetState()
        {
            return keyboard;
        }

        KeyboardState IKeyboardDriver2.GetState(int index)
        {
            if (index == 0)
                return keyboard;
            else
                return new KeyboardState();
        }

        string IKeyboardDriver2.GetDeviceName(int index)
        {
            return "Default Windows Keyboard";
        }

        #endregion
    }
}
