using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

namespace PlayerInput
{
    public class KeyboardMouseInputSource<TTarget> : InputSource<TTarget> where TTarget : MonoBehaviour
    {
        private Dictionary<InputButton, KeyCode> buttonMappingKeyboard;
        private Dictionary<InputButton, int> buttonMappingMouse;
        private KeyCode rangedActivateMapping;
        private KeyCode fireMapping;

        private KeyboardAxis moveAxis;
        private KeyboardAxis menuAxis;

        private GameObject mouseCenterObject;

        private float perspectiveCorrectY = 0.7f;

        protected override void TargetUpdated(TTarget target)
        {
            mouseCenterObject = target.gameObject;
        }

        private struct KeyboardAxis
        {
            public KeyCode Right;
            public KeyCode Up;
            public KeyCode Left;
            public KeyCode Down;
        }

        public KeyboardMouseInputSource()
        {
            buttonMappingKeyboard = new Dictionary<InputButton, KeyCode>
            {
                { InputButton.MenuSelect, KeyCode.Return },
                { InputButton.MenuCancel, KeyCode.Escape },

                //{ InputButton.UseItem, KeyCode.Space },
                //{ InputButton.PickA, KeyCode.Q },
                //{ InputButton.PickB, KeyCode.E },

                //{ InputButton.AnimalSelector, KeyCode.LeftControl },
            };

            buttonMappingMouse = new Dictionary<InputButton, int>
            {
            };

            rangedActivateMapping = KeyCode.LeftShift;

            moveAxis = new KeyboardAxis()
            {
                Right = KeyCode.D,
                Up = KeyCode.W,
                Left = KeyCode.A,
                Down = KeyCode.S,
            };

            menuAxis = new KeyboardAxis()
            {
                Right = KeyCode.RightArrow,
                Up = KeyCode.UpArrow,
                Left = KeyCode.LeftArrow,
                Down = KeyCode.DownArrow,
            };
        }
        
        public override float Axis(InputAxis axis)
        {
            switch (axis)
            {
                case InputAxis.MoveX:
                    return (Input.GetKey(moveAxis.Right) ? 1.0f : 0.0f) + (Input.GetKey(moveAxis.Left) ? -1.0f : 0.0f);
                case InputAxis.MoveY:
                    return (Input.GetKey(moveAxis.Up) ? 1.0f : 0.0f) + (Input.GetKey(moveAxis.Down) ? -1.0f : 0.0f);
                /*
                case InputAxis.RangedX:
                    if (!Input.GetKey(rangedActivateMapping)) return 0.0f;
                    return GetHeroToMouseVector().x;
                case InputAxis.RangedY:
                    if (!Input.GetKey(rangedActivateMapping)) return 0.0f;
                    return GetHeroToMouseVector().y;
                */
                case InputAxis.MenuX:
                    return (Input.GetKey(menuAxis.Right) ? 1.0f : 0.0f) + (Input.GetKey(menuAxis.Left) ? -1.0f : 0.0f);
                case InputAxis.MenuY:
                    return (Input.GetKey(menuAxis.Up) ? 1.0f : 0.0f) + (Input.GetKey(menuAxis.Down) ? -1.0f : 0.0f);
                //case InputAxis.Throttle:
                //    return Input.GetKey(fireMapping) ? 1.0f : 0.0f;
            }
            return 0;
        }

        private Vector3 GetHeroToMouseVector()
        {
            if (mouseCenterObject == null) return new Vector3();
            Vector3 m = Input.mousePosition;
            Vector3 p = mouseCenterObject.transform.position;
            Vector3 w = Camera.main.WorldToScreenPoint(p);
            Vector3 delta = m - w;
            delta.y *= perspectiveCorrectY;
            return delta.normalized;
        }

        public override bool ButtonDown(InputButton button)
        {
            if (buttonMappingMouse.ContainsKey(button)) return Input.GetMouseButton(buttonMappingMouse[button]);
            if (buttonMappingKeyboard.ContainsKey(button)) return Input.GetKey(buttonMappingKeyboard[button]);
            return false;
        }

        public override bool ButtonPressedThisFrame(InputButton button)
        {
            if (buttonMappingMouse.ContainsKey(button)) return Input.GetMouseButtonDown(buttonMappingMouse[button]);
            if (buttonMappingKeyboard.ContainsKey(button)) return Input.GetKeyDown(buttonMappingKeyboard[button]);
            return false;
        }

        public override bool ButtonReleasedThisFrame(InputButton button)
        {
            if (buttonMappingMouse.ContainsKey(button)) return Input.GetMouseButtonUp(buttonMappingMouse[button]);
            if (buttonMappingKeyboard.ContainsKey(button)) return Input.GetKeyUp(buttonMappingKeyboard[button]);
            return false;
        }
    }
}
