using System.Threading;
using UnityEngine;
using System.Collections;

public class RunningDevice : MonoBehaviour {
    
    // ------------------------------------------------------------------------------------------------------
    // Public attributes
    // ------------------------------------------------------------------------------------------------------

    /// <summary>
    /// Factor used to show th cursor
    /// </summary>
    public Texture2D cursorImage;

    // ------------------------------------------------------------------------------------------------------
    // Private attributes
    // ------------------------------------------------------------------------------------------------------

    int goalFPS = 30;

    int millisecondsToWait = 0;

    private int cursorWidth = 25;

    private int cursorHeight = 25;

    Vector3 deviceCursorPosition;

    bool isDragging;
    bool isRotating;
    bool isGyroMode;

    bool objectSelected;

    RaycastHit hit;

    Ray ray;

    float distance;

    /// <summary>
    /// Factor used to smooth rotation data
    /// </summary>
    public float PlayerSmoothRotationFactor = 0.1f;
    // ------------------------------------------------------------------------------------------------------
    // Private attributes
    // ------------------------------------------------------------------------------------------------------

    /// <summary>
    /// Used to read or not form the dll
    /// </summary>
    private bool bCanReadDll;

    /// <summary>
    /// Device values
    /// </summary>
    private DeviceValues mDeviceValues;

    /// <summary>
    /// Get or set actor's parent transform
    /// </summary>
    public virtual Transform Parent
    {
        get { return mTransform.parent; }
        set { mTransform.parent = value; }
    }

    /// <summary>
    /// Speed up access for transform data
    /// </summary>
    protected Transform mTransform;

    /// <summary>
    /// Get or set object's transform
    /// </summary>
    public virtual Transform Transfrom
    {
        get { return mTransform; }
        set { mTransform = value; }
    }

    /// <summary>
    /// Get or set actor's rotation
    /// </summary>
    public virtual Quaternion Rotation
    {
        get { return mTransform.rotation; }
        set { mTransform.rotation = value; }
    }

    public float draggingX, draggingY, draggingZ;

    public float pointingX, pointingY;


	// Use this for initialization
	void Start () {

        mTransform = gameObject.transform;

        mDeviceValues = new DeviceValues();

        bCanReadDll = false;

        Invoke("Start_iOS", 1);

        mTransform.localPosition = new Vector3(20, 5, 5);

        objectSelected = false;

        //Screen.showCursor = false;
	}
	
	// Update is called once per frame
    void Update()
    {

        if (bCanReadDll)
        {
            iOSDevice.VRPNDLLClient_ReadDevice(out mDeviceValues);

            isDragging = (mDeviceValues.buttons & 0x40)==0x40?true:false;
            //isRotating = (mDeviceValues.buttons & 0x20)==0x20?true:false;
            //isGyroMode = (mDeviceValues.buttons & 0x10)==0x10?true:false;

            //Is dragging?
            if (isDragging)
            {
                if (objectSelected)
                {
                    mTransform.rotation = Quaternion.Lerp(mTransform.rotation,
                                                                Quaternion.Euler(mDeviceValues.pitch * 0.36f,
                                                                        mDeviceValues.yaw * -0.36f,
                                                                        mDeviceValues.roll * 0.36f),
                                                                PlayerSmoothRotationFactor);
                    //draggingX = mTransform.localPosition.x;
                    //draggingY = mTransform.localPosition.y;
                    //draggingZ = mTransform.localPosition.z;

                    draggingX = (mDeviceValues.deltaX) * -0.1f;
                    draggingY = (mDeviceValues.deltaZ) * 0.1f;
                    draggingZ = (mDeviceValues.deltaY) * -0.1f;

                    mTransform.localPosition = new Vector3(draggingX, draggingZ, draggingY);
                }
            }
            //Is pointing?
            else
            {
                pointingX = mDeviceValues.deltaX + Screen.width / 2;
                pointingY = mDeviceValues.deltaY + Screen.height / 2;
                if (pointingX < 0)
                {
                    pointingX = 0;
                }
                if (pointingX > Screen.width-10)
                {
                    pointingX = Screen.width-10;
                }
                if (pointingY < 0)
                {
                    pointingY = 0;
                }
                if (pointingY > Screen.height - 10)
                {
                    pointingY = Screen.height - 10;
                }
                deviceCursorPosition.x = pointingX;
                deviceCursorPosition.y = Screen.height - pointingY;
                deviceCursorPosition.z = 0;

                ray = Camera.main.ScreenPointToRay(deviceCursorPosition);

                distance = 100.0f;
                Physics.Raycast(ray, out hit, distance);
                try
                {
                    if (hit.collider.isTrigger)
                    {
                        objectSelected = true;
                    }
                    else
                    {
                        objectSelected = false;
                    }
                }
                catch
                {
                    objectSelected = false;
                }
            }
        }

        //Adjust the sleep time
        double overflow = 1.0 / goalFPS - Time.deltaTime;

        if (overflow > 0.0)
            millisecondsToWait++;
        else
            millisecondsToWait--;

        Thread.Sleep(Mathf.Clamp(millisecondsToWait, 0, (int)(1.0 / goalFPS * 1000.0))); // clamp for sanity 

    }

    void OnGUI()
    {
        //Is pointing?
        if (!isDragging)
        {
            GUI.DrawTexture(new Rect(pointingX, pointingY, cursorWidth, cursorHeight), cursorImage);
            //objectSelected = false;
            //Debug.Log("Object Released");
        }
    }

    private void Start_iOS()
    {
        //Debug.Log("Starting iOS Device....");
        iOSDevice.VRPNDLLClient_SetupDevice("iOS0@localhost", 0, 1, 2, 3, 4, 5, 6);
        //Debug.Log("Starting iOS device....");
        iOSDevice.VRPNDLLClient_StartDevice();
        //Debug.Log("Reading iOS device....");
        StartReadFromDevice();
    }

    /// <summary>
    /// Allow the object to read from the dll
    /// </summary>
    public void StartReadFromDevice()
    {
        bCanReadDll = true;
    }

    /// <summary>
    /// Stop the object to read from the dll
    /// </summary>
    public void StopReadFromDevice()
    {
        bCanReadDll = false;
    }
}
