using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;

public class Planemovement : FlatlandMovement
{
    public double starttime = 0.0f;
    public Planemovement otherclock;


    void Start()
    {
        base.Start();
        //Renderer r = theobject.GetComponent<Renderer>();
        //Color materialColor = r.material.color;
        //r.material.color = Color.clear;
        v = new Vector3(0.0f, 0.0f, 0.0f);
        //playergamma = 1.0f;
        orientation = new Vector3(0.0f, 0.0f, 1.0f);
        time = starttime;
        gamma = 1.0f;
    }

    // Update is called once per frame
    void Update()
    {
        base.Update();
    }

    // For physics calcs
    void FixedUpdate()
    {
        base.FixedUpdate();

        var prevup = transform.up;
        var prevfor = transform.forward;
        var prevorient = orientation;
        transform.Translate((float)Constants.c * Vector3.up * Time.fixedDeltaTime * (float)levelManager.player.gamma, Space.World); // move up by 1 second
        
        cnt++;
        if (cnt % 480 == 0)
        {
            cnt = 0;
        }

        //alpha = 4 * Vector3.forward * Mathf.Cos(2 * Mathf.PI * cnt / 480) + 4 * Vector3.left * Mathf.Sin(2 * Mathf.PI * cnt / 480);

        if ((levelManager.player.transform.position - transform.position).magnitude < 1f)
        {
            toggle = true;
        }
        else
        {
            toggle = false;
        }

        if (toggle && Input.GetKeyDown("g"))
        {
            grabbed = !grabbed;
        }

        if (grabbed)
        {
            v = levelManager.player.v;
            Debug.Log("being grabbed");
        }

        if (alpha.magnitude > 0.0f)
        {

            var dt = (Constants.c / alpha.magnitude) * MathNet.Numerics.Trig.Sinh(alpha.magnitude * Time.fixedDeltaTime / Constants.c);
            var atmp = (alpha.magnitude * dt)
                / Mathf.Sqrt(1 + (float)((alpha.magnitude * dt / Constants.c) * (alpha.magnitude * dt / Constants.c)));
            //var atmp = alpha.magnitude * Time.fixedDeltaTime;



            double[] vtmp = { (atmp * (alpha.x / alpha.magnitude)), 0.0, (atmp * (alpha.z / alpha.magnitude)) };
            var deltavnaive = V.DenseOfArray(vtmp);

            double[] tmp = {Constants.c * Constants.Gamma(deltavnaive.L2Norm()),
                      deltavnaive[0] * Constants.Gamma(deltavnaive.L2Norm()),
                      deltavnaive[2] * Constants.Gamma(deltavnaive.L2Norm())};

            var deltav = V.DenseOfArray(tmp);


            if (v.magnitude > 0.0f)
            {
                deltav = Constants.BoostMatrix(-v) * deltav;
            }

            var tt = deltav[0] / Constants.c;

            Vector3 finaldeltav = new Vector3((float)(deltav[1] / tt), 0.0f, (float)(deltav[2] / tt));

            var hmm = finaldeltav - v;

            v = finaldeltav;
        }

        if (v.magnitude >= Constants.c) // if floating point errors makes object ftl
            v = v.normalized * (float)(0.999999f * Constants.c);


        beta = v.magnitude / (float)Constants.c;

        gamma = Constants.Gamma(v.magnitude);



        transform.Translate(v * Time.fixedDeltaTime * (float)gamma, Space.World);

        var vt = v + (float)Constants.c * Vector3.up;

        vt.x = -vt.x;

        vt.z = -vt.z;

        vt.Normalize();


        transform.localScale = new Vector3(1.0f, 1.0f, 1.0f); // release child to change x'-axis scale

        var neworientation = (Quaternion.FromToRotation(Vector3.up, vt)) * orientation;

        theobject.transform.rotation = Quaternion.LookRotation(neworientation, vt);

        theobject.transform.parent = null;

        Vector3 newforward = new Vector3(vt.y * (v.x / v.magnitude), Mathf.Sqrt(vt.x * vt.x + vt.z * vt.z), vt.y * (v.z / v.magnitude));

        transform.rotation = Quaternion.LookRotation(newforward, vt);

        theobject.transform.parent = transform;
        theobject.transform.localScale = startScale;


        transform.localScale = new Vector3(1.0f, 1.0f, (float)gamma); // scale x'-axis scale (distance dilation)

        time += Time.fixedDeltaTime * (float)(levelManager.player.gamma / gamma);
    }

    public override void OnCollisionStaychild(Collision collision)
    {
        base.OnCollisionStaychild(collision);
        //Debug.Log("hit!");
        //if(collision.transform.parent.name != "AnObject(Clone)")
        //    Debug.Log(collision.gameObject.name + " wow!");
        if (collision.transform.parent != null)
        {
            var x = collision.transform.parent.gameObject.GetComponent(typeof(Planemovement)) as Planemovement;
            if (x != null && x.Equals(otherclock))
            {
                Debug.Log("hit!");
                if (Mathf.Abs((float)(otherclock.GetTime() - time)) <= 1.0f)
                {
                    levelManager.winstate = true;
                }
            }
        }
       
    }

    public double GetTime()
    {
        return time;
    }
}
