using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Ruby;
using VALUE = System.Int32;
using StarEngine.Core;

namespace StarEngine.Ruby
{
    public partial class RubyInterpreter
    {
        private void InitializeInputModule()
        {
            VALUE mInput = SERubyConsts.ForName("Input");

            RUBY.rb_define_singleton_method(mInput, "__cs_pressed_keys__", this.mInput_cs_pressed_keys);
            RUBY.rb_define_singleton_method(mInput, "mouse_location", this.mInput_mouse_location);
        }

        private VALUE mInput_cs_pressed_keys(VALUE self, VALUE rbDevice, VALUE rbOptions)
        {
            IInput input = this.GameEnvironment.Input;

            VALUE rbKeys = RUBY.rb_ary_new();

            string csDevice = RUBY.StringValuePtr(RUBY.Send(rbDevice, "to_s"));
            int csDeviceNumber = RUBY.NUM2INT(RUBY.HashAref(rbOptions, "device_number"));
            int csDuration = RUBY.NUM2INT(RUBY.HashAref(rbOptions, "duration"));
            int csDelay = RUBY.NUM2INT(RUBY.HashAref(rbOptions, "delay"));
            int csInterval = RUBY.NUM2INT(RUBY.HashAref(rbOptions, "interval"));
            
            if (csDevice == "keyboard")
            {
                Keys[] keys = input.GetPressedKeyboardKeys(csDuration, csDelay, csInterval);
                foreach (Keys key in keys)
                    RUBY.rb_ary_push(rbKeys, RUBY.Intern(key.ToString().ToLower()));
            }
            else if (csDevice == "game_pad")
            {
                GamePadDirections directions = input.GetPressedGamePadDirections(csDeviceNumber, csDuration, csDelay, csInterval);
                if ((directions & GamePadDirections.Down) != 0)
                    RUBY.rb_ary_push(rbKeys, RUBY.Intern("down"));
                if ((directions & GamePadDirections.Left) != 0)
                    RUBY.rb_ary_push(rbKeys, RUBY.Intern("left"));
                if ((directions & GamePadDirections.Right) != 0)
                    RUBY.rb_ary_push(rbKeys, RUBY.Intern("right"));
                if ((directions & GamePadDirections.Up) != 0)
                    RUBY.rb_ary_push(rbKeys, RUBY.Intern("up"));

                int[] buttons = input.GetPressedGamePadButtons(csDeviceNumber, csDuration, csDelay, csInterval);
                foreach (int button in buttons)
                    RUBY.rb_ary_push(rbKeys, RUBY.INT2NUM(button));
            }
            else if (csDevice == "mouse")
            {
                MouseButtons buttons = input.GetPressedMouseButtons(csDuration, csDelay, csInterval);
                if ((buttons & MouseButtons.Left) != 0)
                    RUBY.rb_ary_push(rbKeys, RUBY.Intern("left"));
                if ((buttons & MouseButtons.Middle) != 0)
                    RUBY.rb_ary_push(rbKeys, RUBY.Intern("middle"));
                if ((buttons & MouseButtons.Right) != 0)
                    RUBY.rb_ary_push(rbKeys, RUBY.Intern("right"));
            }
            else
            {
                RUBY.rb_raise(SERubyConsts.ForName("::ArgumentError"), "invalid device: " + csDevice);
            }

            RUBY.Send(rbKeys, "freeze");
            return rbKeys;
        }

        private VALUE mInput_mouse_location(VALUE self)
        {
            Point csMouseLocation = this.GameEnvironment.Input.MouseLocation;
            VALUE rbMouseLocation = RUBY.rb_ary_new();
            RUBY.rb_ary_push(rbMouseLocation, RUBY.INT2NUM(csMouseLocation.X));
            RUBY.rb_ary_push(rbMouseLocation, RUBY.INT2NUM(csMouseLocation.Y));
            return rbMouseLocation;
        }
    }
}
