using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Turretscript2: MonoBehaviour {

  public bool Playercontrolled;
  private HingeJoint turretjoint;
  public GameObject Turret;
  private HingeJoint cannonjoint;
  public Transform Cannon;
  public float turretcrankspeed;

  public float cannoncrankspeed;

  public Transform Widget;
  public float motorforce;
  public float aimed_ThresholdTolerance = 10;

  JointMotor motor;
  JointMotor motor1;

  public bool centeraim;
  public bool fixedaim;
  public Widgetcamera wgcam;

  public float centeraim_dist;

  public Transform importcamtransform;

  private Vector3 fixedaimpoint;
  private bool freelook;
  public bool aimed;
  private Vector3 refvector;
  private Vector3 refvector2;
  private float turretdif;
  private float cannondif;

  private float aimCorrectionfromcamera;
  private float aimpointdistace;

  private float offsetforturrets;

  private Transform actualcamtransform;

  private bool spawnedindicator = false;

  private GameObject Aimingaid;

  // Start is called before the first frame update
  void Start() {

    Cursor.lockState = CursorLockMode.Locked;
    freelook = false;

    if (Playercontrolled) {

      if (Widget.GetComponent < Widgetcamera > () != null)
        wgcam = Widget.GetComponent < Widgetcamera > ();

    }

    if (Turret.GetComponent < HingeJoint > () != null)
      turretjoint = Turret.GetComponent < HingeJoint > ();

    if (Cannon.GetComponent < HingeJoint > () != null)
      cannonjoint = Cannon.GetComponent < HingeJoint > ();
  }

  // Update is called once per frame

  void Update()

  {

    // if player controls turret

    if (Playercontrolled) {

      if (!spawnedindicator)

      {

        Aimingaid = (GameObject) Instantiate(Resources.Load("UI/turretaimgizmo"), gameObject.transform.position, gameObject.transform.rotation);
        TurretIndicatorCircle aimingscript = Aimingaid.GetComponent < TurretIndicatorCircle > ();
        aimingscript.turret_to_indicate = Turret.GetComponent < Shoot > ();
        BillboardBehaviour bill = Aimingaid.GetComponent < BillboardBehaviour > ();
        bill.camera = wgcam.camera.transform;
        spawnedindicator = true;
      }

      actualcamtransform = wgcam.camtransform;
      aimCorrectionfromcamera = actualcamtransform.InverseTransformPoint(transform.position).x;
      offsetforturrets = wgcam.offsetforturrets;
      aimpointdistace = wgcam.aimpointdistace;

      if (Aimingaid != null) {
        RaycastHit hit;
        if (Physics.Raycast(Cannon.position, Cannon.forward, out hit, aimpointdistace)) {
          Aimingaid.transform.position = hit.point;
        } else {
          Aimingaid.transform.position = Cannon.TransformPoint(0, 0, aimpointdistace);
        }

      }

      // button controls
      if (Input.GetKeyDown("v")) {
        centeraim = !centeraim;
      }

      if (Input.GetKeyDown("b")) {
        fixedaim = !fixedaim;
      }

      if (Input.GetKeyDown("c")) {
        freelook = !freelook;
      }

      if (Input.GetMouseButton(1)) {

        fixedaimpoint = actualcamtransform.TransformPoint(aimCorrectionfromcamera, offsetforturrets, aimpointdistace);

      }

      // aim methods

      CopyForwardofTransform(actualcamtransform);

      if (centeraim) {
        PointAtTargetPoint(actualcamtransform.TransformPoint(aimCorrectionfromcamera, offsetforturrets, aimpointdistace));
      } else if (fixedaim) {

        PointAtTargetPoint(fixedaimpoint);

      }

    } else
      CopyForwardofTransform(Widget);

    if (!freelook) {
      if (Turret != null)
        turretcontrol(refvector);

      if (Cannon != null)
        cannoncontrol(refvector2);

      if (Turret != null && Cannon != null) {
        if (Mathf.Abs(turretdif) < aimed_ThresholdTolerance && Mathf.Abs(cannondif) < aimed_ThresholdTolerance)
          aimed = true;
        else
          aimed = false;

      } else if (Turret != null && Cannon == null) {
        if (Mathf.Abs(turretdif) < aimed_ThresholdTolerance)
          aimed = true;
        else
          aimed = false;

      } else if (Turret == null && Cannon != null) {
        if (Mathf.Abs(cannondif) < aimed_ThresholdTolerance)
          aimed = true;
        else
          aimed = false;

      }

    }

  }

  void CopyForwardofTransform(Transform transform) {
    refvector = Vector3.ProjectOnPlane(transform.forward, Turret.transform.up);
    refvector2 = Vector3.ProjectOnPlane(transform.forward, Cannon.right);

  }

  void PointAtTargetPoint(Vector3 point) {

    refvector2 = Vector3.ProjectOnPlane((point - Cannon.position), Cannon.right);
    refvector = Vector3.ProjectOnPlane((point - Turret.transform.position), Turret.transform.up);

    Debug.DrawRay(Cannon.position, (point - Cannon.position) * 10, Color.green);
    Debug.DrawRay(Cannon.position, Cannon.forward * 10000, Color.red);

  }

  void turretcontrol(Vector3 refvector)

  {

    //turret rotation

    Vector3 turretforward = Vector3.ProjectOnPlane(Turret.transform.forward, Turret.transform.up);

    turretdif = Vector3.SignedAngle(refvector, turretforward, Turret.transform.up);

    motor.freeSpin = false;
    turretjoint.motor = motor;
    turretjoint.useMotor = true;

    float speed = Mathf.Clamp(Mathf.Abs(turretcrankspeed * (turretdif / 5)), 0, turretcrankspeed * 2);

    if (turretdif < turretcrankspeed / 100 && turretdif > -(turretcrankspeed / 100)) {

      motor = turretjoint.motor;
      motor.force = motorforce;
      motor.targetVelocity = 0;

    } else {

      if (turretdif < 0) {
        motor = turretjoint.motor;
        motor.force = motorforce;
        motor.targetVelocity = speed;

      }

      if (turretdif > 0)

      {
        motor = turretjoint.motor;
        motor.force = motorforce;
        motor.targetVelocity = -speed;

      }

    }

  }

  void cannoncontrol(Vector3 refvector2)

  {

    //Cannon elevation;

    Vector3 cannonforward = Vector3.ProjectOnPlane(Cannon.forward, Cannon.right);
    cannondif = Vector3.SignedAngle(refvector2, cannonforward, Cannon.right);

    motor1.freeSpin = false;
    cannonjoint.motor = motor1;
    cannonjoint.useMotor = true;

    float canspeed = Mathf.Clamp(Mathf.Abs(cannoncrankspeed * (cannondif / 5)), 0, cannoncrankspeed * 2);

    if (cannondif == 0) {

      motor1 = cannonjoint.motor;
      motor1.force = motorforce;
      motor1.targetVelocity = 0;

    } else {

      if (cannondif < 0) {
        motor1 = cannonjoint.motor;
        motor1.force = motorforce;
        motor1.targetVelocity = canspeed;

      }

      if (cannondif > 0)

      {
        motor1 = cannonjoint.motor;
        motor1.force = motorforce;
        motor1.targetVelocity = -canspeed;

      }

    }

  }

}