﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection;
using Gaazar;


public struct InputInfo
{
    public bool buttonDown;
    public MemberInfo member;
}

public abstract class InputHandler : MonoBehaviour
{
    public Dictionary<string, InputInfo> dict;
    public Dictionary<string, string> keyName = new Dictionary<string, string>();
    private void Update()
    {


        MonoUpdate();
    }
    private void Start()
    {
        dict = new Dictionary<string, InputInfo>();
        foreach (FieldInfo i in this.GetType().GetFields(BindingFlags.Instance|BindingFlags.NonPublic))
        {
            var a = i.GetCustomAttribute<InputAttribute>();
            if (a != null)
            {
                InputInfo inf = new InputInfo();
                inf.member = i;inf.buttonDown = false;
                dict.Add(a._name, inf);
                keyName.Add(a._key,a._name);
                //Debug.Log(a._key + " " + a._name);

            }
        }
        MonoStart();
    }
    public void PostInput(string name,Vector2 axis)
    {
        InputInfo mi;
        if (dict.TryGetValue(name, out mi))
        {
            FieldInfo fi;
            if (mi.member.MemberType == MemberTypes.Field)
            {
                fi = mi.member as FieldInfo;
                if (fi.FieldType == typeof(Vector2))
                {
                    fi.SetValue(this,axis);
                }
                if (fi.FieldType == typeof(float))
                {
                    fi.SetValue(this, axis.x);
                }
                if (fi.FieldType == typeof(int))
                {
                    fi.SetValue(this, axis.x>=0.5f?1:0);
                }
                if (fi.FieldType == typeof(bool))
                {
                    fi.SetValue(this, axis.x >= 0.5f);
                }
            }
            if (mi.member.MemberType == MemberTypes.Method)
            {
                MethodInfo mei;
                mei = mi.member as MethodInfo;
                ParameterInfo[] pis = mei.GetParameters();
                if (pis.Length == 1)
                {
                    if (pis[0].ParameterType == typeof(Vector2)) mei.Invoke(this, new object[] { axis });
                    if (pis[0].ParameterType == typeof(bool)) mei.Invoke(this, new object[] { axis.x>=0.5 });
                    if (pis[0].ParameterType == typeof(float)) mei.Invoke(this, new object[] { axis.x });

                }
            }
        }
    }
    public void PostInput(string name, bool buttonDown)
    {
        InputInfo mi;
        if (dict.TryGetValue(name, out mi))
        {
            FieldInfo fi;
            if (mi.member.MemberType == MemberTypes.Field)
            {
                fi = mi.member as FieldInfo;
                if (fi.FieldType == typeof(Vector2))
                {
                    fi.SetValue(this, new Vector2(buttonDown? 1 : 0,0));
                }
                if (fi.FieldType == typeof(bool))
                {
                    fi.SetValue(this, buttonDown);
                }
                if (fi.FieldType == typeof(int))
                {
                    fi.SetValue(this, buttonDown?0:1);
                }
                if (fi.FieldType == typeof(float))
                {
                    fi.SetValue(this, buttonDown ? 0 : 1);
                }
            }
            if (mi.member.MemberType == MemberTypes.Method)
            {
                MethodInfo mei;
                mei = mi.member as MethodInfo;
                ButtonEvent eventType;
                if (buttonDown)
                {
                    if (!mi.buttonDown)
                    {
                        //mei.Invoke(this, new object[] { ButtonEvent.Down });
                        eventType = ButtonEvent.Down;
                        mi.buttonDown = true;
                    }
                    else
                    {
                        //mei.Invoke(this, new object[] { ButtonEvent.Hold });
                        eventType = ButtonEvent.Hold;
                    }
                }
                else
                {
                    //mei.Invoke(this, new object[] { ButtonEvent.Up });
                    eventType = ButtonEvent.Up;
                    mi.buttonDown = false;

                }
                ParameterInfo[] pis = mei.GetParameters();
                if (pis.Length == 1)
                {
                    if (pis[0].ParameterType == typeof(Vector2)) mei.Invoke(this, new object[] {new Vector2(buttonDown?1:0,0)});
                    if (pis[0].ParameterType == typeof(bool)) mei.Invoke(this, new object[] { buttonDown });
                    if (pis[0].ParameterType == typeof(float)) mei.Invoke(this, new object[] { buttonDown ? 1 : 0 });
                    if (pis[0].ParameterType == typeof(ButtonEvent)) mei.Invoke(this, new object[] { eventType });

                }
            }
        }

    }
    public void PostInput(string name, float val)
    {
        InputInfo mi;
        if (dict.TryGetValue(name, out mi))
        {
            FieldInfo fi;
            if (mi.member.MemberType == MemberTypes.Field)
            {
                fi = mi.member as FieldInfo;
                if (fi.FieldType == typeof(float))
                {
                    fi.SetValue(this, val);
                }
            }
            if (mi.member.MemberType == MemberTypes.Method)
            {
                MethodInfo mei;
                mei = mi.member as MethodInfo;
                ParameterInfo[] pis = mei.GetParameters();
                if (pis.Length == 1)
                {
                    if (pis[0].ParameterType == typeof(Vector2)) mei.Invoke(this, new object[] { new Vector2(val, 0) });
                    if (pis[0].ParameterType == typeof(bool)) mei.Invoke(this, new object[] { val==0 });
                    if (pis[0].ParameterType == typeof(float)) mei.Invoke(this, new object[] { val>=0.5 ? 1 : 0 });

                }
            }
        }
    }

    public virtual void MonoStart() { }
    public virtual void MonoUpdate() { }
}
