// BGG -- observermove for 2020 Unity and later, left/right/up/down, w/s/a/d,
// and left-joystick controls movement
//
// SHIFT-left/right/up/down, SHIFT-w/s/a/d, and "Fire1"/"Fire3" buttons control
// rotation
//
// it will go forward where you are looking in VR
// 11/7/2023

using UnityEngine;


public class observermove : MonoBehaviour
{
    public float speed = 3.0f;
    public float rotationspeed = 1.0f;
    public float mrotationspeed = 1.0f; // mrotation used for joystick rotation, too
    float prevrot; // will need a better way than 'prevrot' (for the view-tracking)
    float basespeed; // to store the editor/interface main speed if we need to change it

    Camera cam;

    bool halt;

    public void Awake()
    {
        cam = Camera.main;
    }

    // Use this for initialization
    void Start()
    {
        prevrot = 1.0f;
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
        halt = false;
        basespeed = speed;

        Vector3 cent = gameObject.GetComponent<CapsuleCollider>().center;

        /*  this is an older approach to fixing the height for vive
        float hh = cam.transform.position.y;
        float scale = 1.0f / hh;
        transform.localScale = Vector3.one * scale;
        */

        // BGG -- not sure this is general; done for "myplaces"
        // this returns "Vive.Mv" or "Oculus Rift CV1" (probably others...)
        // XRDevice.model, no "model"
        /*
               string model = UnityEngine.XR.XRDevice.model;
               string tmodel = null;
               if (model.Length > 4)
                   tmodel = model.Remove(4); // look for "Vive" or "Ocul"

               // height adjustment for vive
               if (string.Compare(tmodel, "Vive") == 0)
               {      
                   float tmpy = transform.position.y;
                   transform.position = new Vector3(transform.position.x, 0.0f, transform.position.z);
                   float viveheight = cam.transform.position.y;
                   transform.position = new Vector3(transform.position.x, tmpy - viveheight, transform.position.z);
                   gameObject.GetComponent<CapsuleCollider>().center = new Vector3(cent.x, cent.y + viveheight, cent.z);
               }
        */
    }

    public void stopmotion()
    {
        halt = true;
    }

    public void setspeed(float sp)
    {
        speed = sp;
    }

    public void resetspeed()
    {
        speed = basespeed;
    }

    private void Update()
    {
        if (Input.GetMouseButton(0) || Input.GetMouseButton(1) || Input.GetMouseButton(2))
        {
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;
        }
    }


    // Update is called once per frame
    void FixedUpdate()
    {
        if (halt) return;

        Vector3 movement = new Vector3(0.0f, 0.0f, 0.0f);

        // this is the body and view rotation with left/right arrows
        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) // rotation via SHIFT key
        {
            if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey("a"))
            {
                transform.Rotate(0.0f, -rotationspeed, 0.0f);
            }
            if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey("d"))
            {
                transform.Rotate(0.0f, rotationspeed, 0.0f);
            }

            // rotate the camera to look up and down if VR not attached
            if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey("w"))
            {
                cam.transform.Rotate(-rotationspeed, 0.0f, 0.0f);
            }
            if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey("s"))
            {
                cam.transform.Rotate(rotationspeed, 0.0f, 0.0f);
            }
        }

        // this is the arrow-key movement forward/backwards left/right with all arrow keys
        //  and with w/s keys a/d keys
        // also for xbox joystick axes
        else // if SHIFT was active above, don't do this or it moves when you rotate
        {
            // this is so the secret up & down below will work without movement.  I really need
            // to redo the logic on this
            if (!(Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.LeftAlt))) // added ALT for OSX
            {
                float moveHorizontal = Input.GetAxis("Horizontal");
                float moveVertical = Input.GetAxis("Vertical");
                movement = new Vector3(moveHorizontal, 0.0f, moveVertical);

                // go where we're looking, and shift the front/back/left/right orientation
                // subtract our current world rotation from the amount the camera wants to rotate
                float rotator = cam.transform.eulerAngles.y - transform.eulerAngles.y;
                transform.Rotate(0.0f, rotator, 0.0f);
                transform.Translate(movement * speed * Time.deltaTime);  // move in the camera direction
                transform.Rotate(0.0f, -rotator, 0.0f);  // and set us back on the world coordinates
            }
        }


        // non-SHIFT rotations below
        // rotation via xbox left joystick
        // BGG left in for "myplaces" project. HorizontalTurn now done by "Fire1"/"Fire3" buttons below
        /*
                if (Input.GetAxis("HorizontalTurn") < 0)
                {
                    transform.Rotate(0.0f, -rotationspeed, 0.0f);
                }
                if (Input.GetAxis("HorizontalTurn") > 0)
                {
                    transform.Rotate(0.0f, rotationspeed, 0.0f);
                }
        */

        // BGG "shift" key is also the "Fire3" button, set it so it doesn't go with controller
        // "Fire1/Fire3" buttons if controller attached
        string[] joys = Input.GetJoystickNames();
        int controllerCount = 0;
        for (int i = 0; i < joys.Length; i++)
        {
            if (joys[i] != "") controllerCount += 1;
        }
        if (controllerCount > 0)
        {
            if (Input.GetButton("Fire3"))
                transform.Rotate(0.0f, -rotationspeed, 0.0f);
            if (Input.GetButton("Fire1"))
                transform.Rotate(0.0f, rotationspeed, 0.0f);
        }

        // rotation via mouse movement
        if (Input.GetAxis("Mouse X") < 0)
        {
            transform.Rotate(0.0f, -mrotationspeed * 2.0f, 0.0f);
        }
        if (Input.GetAxis("Mouse X") > 0)
        {
            transform.Rotate(0.0f, mrotationspeed * 2.0f, 0.0f);
        }
        // rotate the camera via mouse movement to look up and down if VR not attached
        // too jerky, use mouse for left/right rotation only
        /*
        if (Input.GetAxis("Mouse Y") < 0)
        {
            cam.transform.Rotate(mrotationspeed * 2.0f, 0.0f, 0.0f);
        }
        if (Input.GetAxis("Mouse Y") > 0)
        {
            cam.transform.Rotate(-mrotationspeed * 2.0f, 0.0f, 0.0f);
        }
        */


        // this is the secret move up and down (if gravity isn't present with up/down arrows)
        if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.LeftAlt)) // added ALT for OSX
        {
            if (Input.GetKey(KeyCode.UpArrow))
            {
                movement = new Vector3(0.0f, 1.0f, 0.0f);
            }
            if (Input.GetKey(KeyCode.DownArrow))
            {
                movement = new Vector3(0.0f, -1.0f, 0.0f);
            }
            transform.Translate(movement * speed * Time.deltaTime);
        }

        // and this is the move up and down from the right joystick
        // "VerticalUp" has to be set up in the Project->Input Manager (5th axis)
        /*
        if (Input.GetAxis("VerticalUp") < 0)
        {
            movement = new Vector3(0.0f, 1.0f, 0.0f);
            transform.Translate(movement * speed * Time.deltaTime);
        }
        if (Input.GetAxis("VerticalUp") > 0)
        {
            movement = new Vector3(0.0f, -1.0f, 0.0f);
            transform.Translate(movement * speed * Time.deltaTime);
        }
        */
    }
}
