using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace Salamax
{
  public static class ButtonStateChanges
  {
    private static byte[] _keyState;
    private static List<IButtonNotifier> _notifiers = new List<IButtonNotifier>();
    public static event EventHandler<EventArgs> ButtonStateChanged;

    public static byte[] KeyStateInfo
    {
      get
      {
        return _keyState;
      }
    }

    public static void AddNotifier(IButtonNotifier notifier)
    {
      _notifiers.Add(notifier);
    }

    public static void RefreshState()
    {
      //Get the current state of our keys (wherever we're receiving key/button updates from)
      var buffer = _GetKeyStates();

      //See if anything changed from last time
      bool changed = false;
      if (_keyState != null)
      {
        for (int i = 0; i < buffer.Length; i++)
        {
          if (buffer[i] != _keyState[i])
          {
            changed = true;
            break;
          }
        }
      }
      _keyState = buffer;

      if (changed && ButtonStateChanged != null)
        ButtonStateChanged(null, EventArgs.Empty);
    }

    private static bool _GetUp()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.Up)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetDown()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.Down)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetLeft()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.Left)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetRight()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.Right)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetGuide()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.Guide)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetA()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.A)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetB()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.B)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetX()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.X)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetY()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.Y)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetStart()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.Start)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetBack()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.Back)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetLeftButton()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.LeftButton)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static bool _GetRightButton()
    {
      bool ret = false;

      foreach (var notifier in _notifiers)
      {
        if (notifier.RightButton)
        {
          ret = true;
          break;
        }
      }

      return ret;
    }

    private static byte _GetLeftTrigger()
    {
      byte ret = 0x00;

      foreach (var notifier in _notifiers)
      {
        if (notifier.LeftTrigger > 0)
        {
          ret = notifier.LeftTrigger;
          break;
        }
      }

      return ret;
    }

    private static byte _GetRightTrigger()
    {
      byte ret = 0x00;

      foreach (var notifier in _notifiers)
      {
        if (notifier.RightTrigger > 0)
        {
          ret = notifier.RightTrigger;
          break;
        }
      }

      return ret;
    }

    private static byte[] _GetKeyStates()
    {
      var ret = new byte[0x14];

      ret[1] = (byte)ret.Length;

      ret[2] |= (byte)(KeyboardInfo.GetKeyState(Keys.Up).IsPressed || _GetUp() ? 0x01 : 0x00);
      ret[2] |= (byte)(KeyboardInfo.GetKeyState(Keys.Down).IsPressed || _GetDown() ? 0x02 : 0x00);
      ret[2] |= (byte)(KeyboardInfo.GetKeyState(Keys.Left).IsPressed || _GetLeft() ? 0x04 : 0x00);
      ret[2] |= (byte)(KeyboardInfo.GetKeyState(Keys.Right).IsPressed || _GetRight() ? 0x08 : 0x00);
      ret[2] |= (byte)(KeyboardInfo.GetKeyState(Keys.S).IsPressed || _GetStart() ? 0x10 : 0x00);
      ret[2] |= (byte)(KeyboardInfo.GetKeyState(Keys.Escape).IsPressed || _GetBack() ? 0x20 : 0x00);
      ret[2] |= (byte)(KeyboardInfo.GetKeyState(Keys.L).IsPressed || _GetLeftButton() ? 0x40 : 0x00);
      ret[2] |= (byte)(KeyboardInfo.GetKeyState(Keys.R).IsPressed || _GetRightButton() ? 0x80 : 0x00);
      ret[3] |= (byte)(KeyboardInfo.GetKeyState(Keys.G).IsPressed || _GetGuide() ? 0x04 : 0x00);
      ret[3] |= (byte)(KeyboardInfo.GetKeyState(Keys.A).IsPressed || _GetA() ? 0x10 : 0x00);
      ret[3] |= (byte)(KeyboardInfo.GetKeyState(Keys.B).IsPressed || _GetB() ? 0x20 : 0x00);
      ret[3] |= (byte)(KeyboardInfo.GetKeyState(Keys.X).IsPressed || _GetX() ? 0x40 : 0x00);
      ret[3] |= (byte)(KeyboardInfo.GetKeyState(Keys.Y).IsPressed || _GetY() ? 0x80 : 0x00);
      ret[4] = _GetLeftTrigger();
      ret[4] = (byte)(KeyboardInfo.GetKeyState(Keys.NumPad1).IsPressed ? 0xFF : 0x00);
      ret[5] = _GetRightTrigger();
      ret[5] = (byte)(KeyboardInfo.GetKeyState(Keys.NumPad2).IsPressed ? 0xFF : 0x00);

      return ret;
    }
  }
}
