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

public enum EShipForm
{
    square =0,
    triangle,
    circle,
}

public class PlayerController : MonoBehaviour
{
    private List<ShapeComponent> myCircles;
    private List<ShapeComponent> myTriangles;
    private List<ShapeComponent> mySquares;

    public GameObject TankTurret;

    public EShipForm currentForm;

    private Vector3 vTurretForward;

    public TM_Weapon BigAss_Beam;
    private float BeamFireInertia;

    public Vector3 vGamePosition;

    public CircleShadowComponent shadow;
    public ClearEnemyProjectilesRing clearProjectilesRing;

    [Space(18)]
    [Header("Camera Jive")]
    public float CamSize_Tank = 10.0f;
    public float CamSize_Jet = 15.0f;
    public float CameraSwitchSpeed = 1.0f;

    [Space(18)]
    [Header("Tank Stats")]
    public float TankTurret_RotateDegreesPerSecond = 150.0f;
    public float TankGround_RotateDegreesPerSecond = 90.0f;
    public float TankMoveSpeed_UnitsPerSecond = 3.0f;
    public float BonusTankSpeedPerCircle = 0.3f;

    private float fTankSpeedBonusFromCircles;

    [Space(18)]
    [Header("Jet Stats")]
    public float JetMaxSpeed_UnitsPerSecond = 10.0f;
    public float JetAcceleration_UnitsPerSecond = 7.0f;
    public float BonusJetSpeedPerCircle = 0.3f;

    [Space(18)]
    [Header("Chargin Ma Lazar")]
    public float BeamChargePerShotCollected = 1.0f;
    public float MaxBeamCharge = 30.0f;
    public GameObject Prefab_FullChargeDebris;
    private float fCurrentBeamCharge;

    [Space(18)]
    [Header("Misc")]
    public float ShapeShiftDelay = 1.0f;
    private float fShapeShiftDelayRemaining;

    [Space(18)]
    [Header("Audio")]
    public AudioClip clip_transform;
    public AudioClip clip_jetTakeDamage;

    public AudioClip clip_gainLaserCharge;
    public AudioClip clip_chargeAtMax;

    private AudioSource mySource;
    private TM_CombatComponent myCC;

    private Vector3 vJetInertia;

    private GameManager theGame;

    private bool bShipDisabled;

    void Awake()
    {
        myCircles = new List<ShapeComponent>();
        myTriangles = new List<ShapeComponent>();
        mySquares = new List<ShapeComponent>();

        currentForm = EShipForm.square;

        vTurretForward = new Vector3(0,0,0);

        mySource = GetComponent<AudioSource>();
        myCC = GetComponent<TM_CombatComponent>();

        theGame = GameObject.Find("GameManager").GetComponent<GameManager>();
    }

	// Use this for initialization
	void Start () 
    {
	    myCC.AddOnHitFunction(OnHitByProjectile);
	}

    public void DisableShip()
    {
        
    }

    public bool NotStartGameAssembledYet()
    {
        return myTriangles.Count < 3 ||
               mySquares.Count < 3 ||
               myCircles.Count < 3;
    }

    IEnumerator VehicleHeight_Coroutine(float fNewHeight, float fSwitchTime)
    {
        float startSize = vGamePosition.z;
        float fTime = 0f;
        while (fTime < fSwitchTime)
        {
            vGamePosition.z = Mathf.Lerp(startSize, fNewHeight, fTime / fSwitchTime);
            fTime += Time.deltaTime;
            yield return null;
        }

        vGamePosition.z = fNewHeight;
    }

    public void ChangeVehicleHeight(float fNewHeight, float fSwitchTime)
    {
        StartCoroutine(VehicleHeight_Coroutine(fNewHeight, fSwitchTime));
    }

    IEnumerator CameraSizeChange_Coroutine( float fNewSize, float fSwitchTime )
    {
        float startSize = Camera.main.orthographicSize;
        float fTime = 0f;
        while (fTime < fSwitchTime)
        {
            Camera.main.orthographicSize = Mathf.Lerp(startSize, fNewSize, fTime/fSwitchTime);
            fTime += Time.deltaTime;
            yield return null;
        }

        Camera.main.orthographicSize = fNewSize;
    }

    public void ChangeCameraSize(float fNewSize, float fSwitchTime)
    {
        StartCoroutine(CameraSizeChange_Coroutine(fNewSize, fSwitchTime));
    }

    public bool OnHitByProjectile(TM_Projectile p)
    {
        if (p.fDamage <= 0.0f)
            return true;

        //if (currentForm == EShipForm.triangle)
        //{
            clearProjectilesRing.ExpandRing();
            TM_AudioManager.PlayClip(clip_jetTakeDamage, mySource);
        //}

        theGame.PlayerWasHit();
        return true;
    }

    public void OnBlockedEnemyShot()
    {
        if (fCurrentBeamCharge >= MaxBeamCharge)
        {
            
        }
        else
        {
            fCurrentBeamCharge++;
            if( fCurrentBeamCharge == MaxBeamCharge)
                TM_AudioManager.PlayClip(clip_chargeAtMax, mySource);
            else
                TM_AudioManager.PlayClip(clip_gainLaserCharge, mySource);
        }
    }

    public void SwitchForms()
    {
        if (fShapeShiftDelayRemaining > 0.0f)
        {
            //play a sound
            return;
        }

        if (currentForm == EShipForm.triangle)
        {
            currentForm = EShipForm.square;
            ChangeCameraSize(CamSize_Tank, CameraSwitchSpeed);
            ChangeVehicleHeight(0, CameraSwitchSpeed);
            theGame.TransitionToGround(CameraSwitchSpeed);
        }
        else
        {
            currentForm = EShipForm.triangle;
            ChangeCameraSize(CamSize_Jet, CameraSwitchSpeed);
            ChangeVehicleHeight(10, CameraSwitchSpeed);
            theGame.TransitionToSky(CameraSwitchSpeed);
        }

        fShapeShiftDelayRemaining = ShapeShiftDelay;

        TM_AudioManager.PlayClip(clip_transform, mySource);
        RealignShapes();

        theGame.bHasChangedShapesInTutorial = true;
    }

	// Update is called once per frame
	void Update ()
	{
        //Don't move during the opening few seconds
        //while we're building shit
	    if (!theGame.bStartGameAssembly)
	    {
	        Update_DebugInput();

	        switch (currentForm)
	        {
	            case EShipForm.square:
	                UpdateTankControls();
	                break;
	            case EShipForm.triangle:
	                UpdateJetControls();
	                transform.position += vJetInertia*Time.deltaTime;
	                if (fCurrentBeamCharge >= MaxBeamCharge)
	                    UpdateFullBeamChargeFX();
	                break;
	        }
	    }

        vGamePosition.x = transform.position.x;
        vGamePosition.y = transform.position.y;

        shadow.fShadowCasterHeight = vGamePosition.z;

        if (fShapeShiftDelayRemaining > 0.0f)
            fShapeShiftDelayRemaining -= Time.deltaTime;
	}

    void UpdateFullBeamChargeFX()
    {
        if (Random.value < 0.35f)
        {
            //spawn a debris
            ShapeComponent s = mySquares[Random.Range(0, mySquares.Count)];
            GameObject go = Instantiate(Prefab_FullChargeDebris);
            go.transform.position = s.transform.position;
            DebrisComponent dc = go.GetComponent<DebrisComponent>();
            dc.Launch();
        }

        //shake a bit
        for (int t = 0; t < mySquares.Count; t++)
        {
            ShapeComponent sc = mySquares[t];
            Vector3 vMove = Random.onUnitSphere;
            vMove.z = 0;
            sc.vPositionAdjustment = vMove.normalized*0.25f;
        }
    }

    void UpdateJetControls()
    {
        //go and face where the left stick points
        Vector2 vLeftStick = TM_InputManager.GetLeftStickNormalized();

        if (vLeftStick != Vector2.zero)
        {
            float fDesiredZ = Vector2.Angle(Vector2.up, vLeftStick);

            if (vLeftStick.x > 0)
                fDesiredZ = 360.0f - fDesiredZ;

            transform.rotation = Quaternion.Euler(0, 0, fDesiredZ);

            //move
            vJetInertia += (Vector3)vLeftStick * (JetAcceleration_UnitsPerSecond ) * Time.deltaTime;

            //cap inertia at max speed
            float fInertiaMag = vJetInertia.magnitude;
            if (fInertiaMag > JetMaxSpeed_UnitsPerSecond)
            {
                vJetInertia.x = (vJetInertia.x / fInertiaMag) * JetMaxSpeed_UnitsPerSecond;
                vJetInertia.y = (vJetInertia.y / fInertiaMag) * JetMaxSpeed_UnitsPerSecond;
            }
        }

        if (BigAss_Beam.bIsFiring)
        {
            vJetInertia += TankTurret.transform.up*-1.0f * BeamFireInertia *Time.deltaTime;
            if (BeamFireInertia > 0.0f)
                BeamFireInertia -= 200.0f*Time.deltaTime;
        }

        //decay jet speed
        if (vJetInertia.x > 0)
            vJetInertia.x -= 3.0f*Time.deltaTime;
        if (vJetInertia.x < 0)
            vJetInertia.x += 3.0f*Time.deltaTime;
        if (vJetInertia.y > 0)
            vJetInertia.y -= 3.0f * Time.deltaTime;
        if (vJetInertia.y < 0)
            vJetInertia.y += 3.0f * Time.deltaTime;

        if( Mathf.Abs( vJetInertia.sqrMagnitude) < 0.01f * 0.01f)
            vJetInertia = Vector3.zero;


        Vector2 vRightStick = TM_InputManager.GetRightStickNormalizedForWorldMovement();

        if (vRightStick != Vector2.zero)
        {
            float fDesiredZ = Vector2.Angle(Vector2.up, vRightStick);

            if (vRightStick.x > 0)
                fDesiredZ = 360.0f - fDesiredZ;

            vTurretForward.z = fDesiredZ;
        }

        TankTurret.transform.rotation = Quaternion.Euler(vTurretForward); 
    }

    #region Tank Controls
    void UpdateTankControls()
    {
        //moving the stix
        Vector2 vRightStick = TM_InputManager.GetRightStickNormalizedForWorldMovement();

        //if the stick is dead this frame, don't change facing or move
        if (vRightStick != Vector2.zero)
        {
            float fRotationSpeed = TankTurret_RotateDegreesPerSecond + (30.0f * fTankSpeedBonusFromCircles);
            float fNewZ = GetAngleAroundAxisBasedOnStickInput(vRightStick, TankTurret.transform.rotation.eulerAngles.z, fRotationSpeed);
            TankTurret.transform.rotation = Quaternion.Euler(0, 0, fNewZ);
        }

        //tank movement
        Vector2 vLeftStick = TM_InputManager.GetLeftStickNormalized();

        //if the stick is more vertical than not, move up or down
        if (vLeftStick != Vector2.zero)
        {
            //get a desired rotation from the left stick
            float fRotationSpeed = TankGround_RotateDegreesPerSecond + (30.0f * fTankSpeedBonusFromCircles);
            float fNewZ = GetAngleAroundAxisBasedOnStickInput(vLeftStick, transform.rotation.eulerAngles.z, fRotationSpeed);
            transform.rotation = Quaternion.Euler(0, 0, fNewZ);

            float fMovementAndFacingScalar = Vector2.Dot(vLeftStick, transform.up);


            Debug.Log("Hey I'm " + fMovementAndFacingScalar);

            float fDelta = TankMoveSpeed_UnitsPerSecond + (TankMoveSpeed_UnitsPerSecond * fTankSpeedBonusFromCircles) * (0.2f + Mathf.Abs(fMovementAndFacingScalar * 0.8f));

            Vector3 vPos = transform.position;
            vPos += (Vector3)vLeftStick*fDelta*Time.deltaTime; // (vLeftStick.y > 0.7f ? -1.0f : 1.0f);
            transform.position = vPos;

            /*
            if (vLeftStick.y > 0.7f || vLeftStick.y < -0.7f)
            {
                float fDelta = TankMoveSpeed_UnitsPerSecond + (TankMoveSpeed_UnitsPerSecond * fTankSpeedBonusFromCircles);

                Vector3 vPos = transform.position;
                vPos += transform.up * fDelta * Time.deltaTime * (vLeftStick.y > 0.7f ? -1.0f : 1.0f);
                transform.position = vPos;
            }
            else
            {
                float fRot = transform.rotation.eulerAngles.z;
                float fRotationSpeed = TankGround_RotateDegreesPerSecond + (30.0f*fTankSpeedBonusFromCircles);
                if (vLeftStick.x < 0.0f)
                    fRot += fRotationSpeed * 0.5f * Time.deltaTime;
                else
                    fRot -= fRotationSpeed * 0.5f * Time.deltaTime;

                if (fRot < 0.0f)
                    fRot += 360.0f;
                else if (fRot >= 360.0f)
                    fRot -= 360.0f;

                transform.rotation = Quaternion.Euler(0, 0, fRot);
            }*/
        }

    }
    #endregion

    float GetAngleAroundAxisBasedOnStickInput(Vector2 vStickValue, float fCurrentRotation, float fRotationSpeed)
    {
        float fDesiredZ = Vector2.Angle(Vector2.up, vStickValue);

        if (vStickValue.x > 0)
            fDesiredZ = 360.0f - fDesiredZ;

        //current z
        float fCurrentZ = fCurrentRotation;

        //Don't wiggle to wiggly
        if (Mathf.Abs(fCurrentZ - fDesiredZ) < 1.0f)
        {
            return fCurrentZ;
        }

        //rotate around counter clockwise if we are in the top quadrant and want to reach top values
        if (fCurrentZ >= 270.0f && fDesiredZ < 90.0f)
        {
            fCurrentZ += fRotationSpeed * Time.deltaTime;
        }
        else if (fCurrentZ <= 90.0f && fDesiredZ >= 270.0f)
        {
            fCurrentZ -= fRotationSpeed * Time.deltaTime;
        }
        else if (fCurrentZ < fDesiredZ)
        {
            fCurrentZ += fRotationSpeed * Time.deltaTime;
        }
        else if (fCurrentZ > fDesiredZ)
        {
            fCurrentZ -= fRotationSpeed * Time.deltaTime;
        }

        if (Mathf.Abs(fCurrentZ - fDesiredZ) < 1.0f)
            fCurrentZ = fDesiredZ;

        return fCurrentZ;
    }

    void Update_DebugInput()
    {
        //add / subtract objects
        if (Input.GetKeyDown(KeyCode.KeypadPlus))
            Debug_AddSquare();
        if (Input.GetKeyDown(KeyCode.KeypadMinus))
            Debug_SubtractSquare();

        if (Input.GetKeyDown(KeyCode.Keypad9))
            Debug_AddCircle();
        if (Input.GetKeyDown(KeyCode.Keypad6))
            Debug_SubtractCircle();

        if (Input.GetKeyDown(KeyCode.Keypad8))
            Debug_AddTriangle();
        if (Input.GetKeyDown(KeyCode.Keypad5))
            Debug_SubtractTriangle();

        if (Input.GetKeyDown(KeyCode.C))
        {
            theGame.GameOver();

            /*
            GameObject go = Instantiate(Resources.Load<GameObject>("prefabs/collectable_time"));
            go.transform.position = transform.position + new Vector3(20, 0, 0);
            CollectableComponent cc = go.GetComponent<CollectableComponent>();
            cc.LaunchCollectable(Vector3.zero, 30.0f,2.0f);
             * */
        }


        float fShotMultiplierFromSpeed = 1.0f;
        if (currentForm == EShipForm.triangle)
        {
            fShotMultiplierFromSpeed += (vJetInertia.magnitude/JetMaxSpeed_UnitsPerSecond);
        }

        //Fire main guns
        if (TM_InputManager.RightTrigger() > 0.5f)
        {
            for (int t = 0; t < myTriangles.Count; t++)
            {
                TM_Weapon gun = null;
                if (currentForm == EShipForm.square)
                {
                    //Increase spread as we get more ground guns
                    gun = myTriangles[t].groundWeapon;
                    
                    if( t > 1)
                        gun.ShotInaccuracy = 5f*t;


                }
                else
                {
                    gun = myTriangles[t].airWeapon;
                    gun.vForceBurstToThisVector = TankTurret.transform.up;
                }

                if (t == 0)
                    gun.bSilent = false;
                else
                    gun.bSilent = true;

                gun.ProjectileSpeedMultiplier = fShotMultiplierFromSpeed;
                gun.StartBurst();
            }
        }

        //Fire beam
        if (TM_InputManager.LeftTrigger() > 0.5f)
        {
            if (fCurrentBeamCharge >= MaxBeamCharge)
            {
                if (BigAss_Beam != null)
                {
                    BigAss_Beam.BeamWidth_Units = mySquares.Count;
                    BigAss_Beam.vFireOriginOffset = new Vector2(0, 2.0f);
                    BigAss_Beam.StartBurst();
                    fCurrentBeamCharge = 0.0f;

                    //blast backwards from firing
                    BeamFireInertia = 200.0f;

                }
            }
            else
            {
                //nope
            }
        }

        if( Input.GetAxis("Mouse ScrollWheel") != 0f || Input.GetAxis("Transform") != 0f)
            SwitchForms();

    }

    public void AddShape(EShipForm shapeStyle, int iCount)
    {
        for (int t = 0; t < iCount; t++)
        {
            switch (shapeStyle)
            {
                case EShipForm.triangle:
                    Debug_AddTriangle();
                    break;
                case EShipForm.square:
                    Debug_AddSquare();
                    break;
                case EShipForm.circle:
                    Debug_AddCircle();
                    break;
            }
        }
    }

    void Debug_AddSquare()
    {
        if (mySquares.Count >= 9)
            return;

        GameObject go = Instantiate(Resources.Load<GameObject>("prefabs/prefab_square"));
        go.transform.position = transform.position;
        go.transform.parent = transform;
        mySquares.Add( go.GetComponent<ShapeComponent>());

        RealignShapes();
    }

    void Debug_SubtractSquare()
    {
        if (mySquares.Count <= 1)
            return;

        ShapeComponent poorBastard = mySquares[Random.Range(0, mySquares.Count)];
        mySquares.Remove(poorBastard);
        poorBastard.transform.parent = null;
        poorBastard.LaunchIntoSpace();

        RealignShapes();
    }

    void Debug_AddCircle()
    {
        if (myCircles.Count >= 9)
            return;

        GameObject go = Instantiate(Resources.Load<GameObject>("prefabs/prefab_circle"));
        go.transform.position = transform.position;
        go.transform.parent = transform;
        myCircles.Add(go.GetComponent<ShapeComponent>());

        RealignShapes();
    }

    void Debug_SubtractCircle()
    {
        if (myCircles.Count <= 1)
            return;

        ShapeComponent poorBastard = myCircles[Random.Range(0, myCircles.Count)];
        myCircles.Remove(poorBastard);
        poorBastard.transform.parent = null;
        poorBastard.LaunchIntoSpace();

        RealignShapes();
    }

    void Debug_AddTriangle()
    {
        if (myTriangles.Count >= 9)
            return;

        GameObject go = Instantiate(Resources.Load<GameObject>("prefabs/prefab_triangle"));
        go.transform.position = transform.position;
        go.transform.parent = transform;
        myTriangles.Add(go.GetComponent<ShapeComponent>());

        RealignShapes();
    }

    void Debug_SubtractTriangle()
    {
        if (myTriangles.Count <= 1)
            return;

        ShapeComponent poorBastard = myTriangles[Random.Range(0, myTriangles.Count)];
        myTriangles.Remove(poorBastard);
        poorBastard.transform.parent = null;
        poorBastard.LaunchIntoSpace();

        RealignShapes();
    }

    public void PrepareForNewGame()
    {
        transform.position = new Vector3(0, 0, -2);
        foreach( ShapeComponent sc in myCircles )
            Destroy(sc.gameObject);
        foreach (ShapeComponent sc in mySquares)
            Destroy(sc.gameObject);
        foreach (ShapeComponent sc in myTriangles)
            Destroy(sc.gameObject);

        myCircles = new List<ShapeComponent>();
        mySquares = new List<ShapeComponent>();
        myTriangles = new List<ShapeComponent>();

        vJetInertia = Vector3.zero;
        fCurrentBeamCharge = 0.0f;
    }

    public void RealignShapes()
    {
        //count up our speed bonuses
        fTankSpeedBonusFromCircles = myCircles.Count * BonusTankSpeedPerCircle;


        List<Vector3> listSquarePositions = new List<Vector3>();
        List<Vector3> listCirclePositions = new List<Vector3>();
        List<Vector3> listTrianglePositions = new List<Vector3>();

        switch (currentForm)
        {
            case EShipForm.square:
                GetSquareOffsets(ref listSquarePositions, ref listCirclePositions, ref listTrianglePositions);
                break;
            case EShipForm.triangle:
                GetTriangleOffsets(ref listSquarePositions, ref listCirclePositions, ref listTrianglePositions);
                break;
        }

        int iNumShapes = 0;

        for (int t = 0; t < mySquares.Count; t++)
        {
            ShapeComponent s = mySquares[t];
            s.MoveToNewTransformOffset( listSquarePositions[t]);

            if (currentForm == EShipForm.square)
                s.transform.localScale = Vector3.one;
            else
                s.transform.localScale = new Vector3(0.75f, 0.75f, 0.75f);

            //attach to the turret if we're in triangle mode;
            if (currentForm == EShipForm.triangle)
            {
                s.transform.parent = TankTurret.transform;
                s.EnableSquareShieldBlockingAction();
            }
            else
            {
                s.transform.parent = transform;
                s.DisableSquareShieldBlockingAction();
            }

            //make sure triangle transform .z is same as the object it is bound to.
            Vector3 fixTransform = s.transform.localPosition;
            fixTransform.z = 0;
            s.transform.localPosition = fixTransform;
            s.transform.localRotation = Quaternion.identity;

            iNumShapes++;

        }

        for (int t = 0; t < myCircles.Count; t++)
        {
            ShapeComponent s = myCircles[t];
            s.MoveToNewTransformOffset(listCirclePositions[t]);
            s.transform.localScale = new Vector3(0.75f,0.75f,0.75f);

            iNumShapes++;
        }
        for (int t = 0; t < myTriangles.Count; t++)
        {
            ShapeComponent s = myTriangles[t];
            s.MoveToNewTransformOffset(listTrianglePositions[t]);

            //triangle logic -- in triangle form, our primary tri is larger
            if (currentForm == EShipForm.triangle)
            {
                if( t == 0)
                    s.transform.localScale = new Vector3(2.0f,2.0f,2.0f);
                else
                    s.transform.localScale = Vector3.one;
            }
            else
                s.transform.localScale = new Vector3(0.75f, 0.75f, 0.75f);

            //attach to the turret if we're in square mode;
            if (currentForm == EShipForm.square)
                s.transform.parent = TankTurret.transform;
            else
                s.transform.parent = transform;

            //make sure triangle transform .z is same as the object it is bound to.
            Vector3 fixTransform = s.transform.localPosition;
            fixTransform.z = 0;
            s.transform.localPosition = fixTransform;
            s.transform.localRotation = Quaternion.identity;

            iNumShapes++;
        }

        float fShadowShapeModifier = 0.7f + (0.1f*(float) iNumShapes);
        shadow.transform.localScale = new Vector3(fShadowShapeModifier, fShadowShapeModifier, fShadowShapeModifier);
    }

    public void GetSquareOffsets(ref List<Vector3> squarePositions, ref List<Vector3> circlePositions, ref List<Vector3> trianglePositions  )
    {
        switch (mySquares.Count)
        {
            case 1:
                squarePositions.Add( new Vector3(0,0,0));
                break;
            case 2:
                squarePositions.Add(new Vector3(0, -0.5f, 0));
                squarePositions.Add(new Vector3(0, 0.5f, 0));
                break;
            case 3:
                squarePositions.Add(new Vector3(0, -1, 0));
                squarePositions.Add(new Vector3(0, 0, 0));
                squarePositions.Add(new Vector3(0, 1, 0));
                break;
            case 4:
                squarePositions.Add(new Vector3(-0.5f, -0.5f, 0));
                squarePositions.Add(new Vector3(-0.5f, 0.5f, 0));
                squarePositions.Add(new Vector3(0.5f, -0.5f, 0));
                squarePositions.Add(new Vector3(0.5f, 0.5f, 0));
                break;
            case 5:
                squarePositions.Add(new Vector3(-0.75f, -0.75f, 0));
                squarePositions.Add(new Vector3(-0.75f, 0.75f, 0));
                squarePositions.Add(new Vector3(0, 0, 0));
                squarePositions.Add(new Vector3(0.75f, -0.75f, 0));
                squarePositions.Add(new Vector3(0.75f, 0.75f, 0));
                break;
            case 6:
                squarePositions.Add(new Vector3(-0.5f, -1f, 0));
                squarePositions.Add(new Vector3(-0.5f, 1f, 0));
                squarePositions.Add(new Vector3(0.5f, -1f, 0));
                squarePositions.Add(new Vector3(0.5f, 1f, 0));
                squarePositions.Add(new Vector3(-0.5f, 0f, 0));
                squarePositions.Add(new Vector3(0.5f, 0f, 0));
                break;
            case 7:
                squarePositions.Add(new Vector3(-0.5f, -1f, 0));
                squarePositions.Add(new Vector3(-0.5f, 1f, 0));
                squarePositions.Add(new Vector3(0.5f, -1f, 0));
                squarePositions.Add(new Vector3(0.5f, 1f, 0));
                squarePositions.Add(new Vector3(-1f, 0f, 0));
                squarePositions.Add(new Vector3(1f, 0f, 0));
                squarePositions.Add(new Vector3(0.0f, 0f, 0));
                break;
            case 8:
                squarePositions.Add(new Vector3(-1f, -1f, 0));
                squarePositions.Add(new Vector3(-1f, 1f, 0));
                squarePositions.Add(new Vector3(1f, -1f, 0));
                squarePositions.Add(new Vector3(1f, 1f, 0));
                squarePositions.Add(new Vector3(-1f, 0f, 0));
                squarePositions.Add(new Vector3(1f, 0f, 0));
                squarePositions.Add(new Vector3(0f, -0.5f, 0));
                squarePositions.Add(new Vector3(0f, 0.5f, 0));
                break;
            case 9:
                squarePositions.Add(new Vector3(1f, 1f, 0));
                squarePositions.Add(new Vector3(-1f, -1f, 0));
                squarePositions.Add(new Vector3(1f, 0f, 0));
                squarePositions.Add(new Vector3(-1f, 0f, 0));
                squarePositions.Add(new Vector3(0f, -1f, 0));
                squarePositions.Add(new Vector3(0f, 1f, 0));
                squarePositions.Add(new Vector3(0f, 0f, 0));
                squarePositions.Add(new Vector3(-1f, 1f, 0));
                squarePositions.Add(new Vector3(1f, -1f, 0));
                break;
        }

        //measure extents 
        float fMinX = 0.0f;
        float fMaxX = 0.0f;
        float fMinY = 0.0f;
        float fMaxY = 0.0f;

        for (int t = 0; t < squarePositions.Count; t++)
        {
            Vector3 v = squarePositions[t];
            if (v.x < fMinX)
                fMinX = v.x;
            if (v.x > fMaxX)
                fMaxX = v.x;
            if (v.y < fMinY)
                fMinY = v.y;
            if (v.y > fMaxY)
                fMaxY = v.y;

        }

        //push out the extents a touch to give room for the spheres
        fMinX -= 0.75f;
        fMaxX += 0.75f;
        fMinY -= 0.75f;
        fMaxY += 0.75f;

        //put spheres in position based on number of spheres
        switch (myCircles.Count)
        {
            case 1:
                circlePositions.Add(new Vector3(0, fMaxY, 0));
                break;
            case 2:
                circlePositions.Add(new Vector3(fMinX, 0, 0));
                circlePositions.Add(new Vector3(fMaxX, 0, 0));
                break;
            case 3:
                circlePositions.Add(new Vector3(fMaxX, 0, 0));
                circlePositions.Add(new Vector3(0, fMaxY, 0));
                circlePositions.Add(new Vector3(fMinX, 0, 0));
                break;
            case 4:
                circlePositions.Add(new Vector3(fMinX, 0.5f, 0));
                circlePositions.Add(new Vector3(fMaxX, 0.5f, 0));
                circlePositions.Add(new Vector3(fMinX, -0.5f, 0));
                circlePositions.Add(new Vector3(fMaxX, -0.5f, 0));
                break;
            case 5:
                circlePositions.Add(new Vector3(fMinX, -0.5f, 0));
                circlePositions.Add(new Vector3(fMaxX, 0.5f, 0));
                circlePositions.Add(new Vector3(0, fMaxY, 0));
                circlePositions.Add(new Vector3(fMaxX, -0.5f, 0));
                circlePositions.Add(new Vector3(fMinX, 0.5f, 0));
                break;
            case 6:
                circlePositions.Add(new Vector3(fMinX, fMinY + 0.25f, 0));
                circlePositions.Add(new Vector3(fMaxX, fMaxY - 0.25f, 0));
                circlePositions.Add(new Vector3(fMaxX, fMinY + 0.25f, 0));
                circlePositions.Add(new Vector3(fMinX, fMaxY - 0.25f, 0));
                circlePositions.Add(new Vector3(fMaxX, -0.0f, 0));
                circlePositions.Add(new Vector3(fMinX, 0.0f, 0));
                break;
            case 7:
                circlePositions.Add(new Vector3(fMinX, fMinY + 0.25f, 0));
                circlePositions.Add(new Vector3(fMaxX, -0.0f, 0));
                circlePositions.Add(new Vector3(fMaxX, fMinY + 0.25f, 0));
                circlePositions.Add(new Vector3(fMinX, fMaxY - 0.25f, 0));
                circlePositions.Add(new Vector3(fMaxX, fMaxY - 0.25f, 0));
                circlePositions.Add(new Vector3(fMinX, 0.0f, 0));
                circlePositions.Add(new Vector3(0, fMaxY, 0));
                break;
            case 8:
                circlePositions.Add(new Vector3(fMinX + 0.12f, fMinY + 0.12f, 0));
                circlePositions.Add(new Vector3(fMinX, fMinY + 1.35f, 0));
                circlePositions.Add(new Vector3(fMinX, fMaxY - 1.35f, 0));
                circlePositions.Add(new Vector3(fMinX + 0.12f, fMaxY - 0.12f, 0));

                circlePositions.Add(new Vector3(fMaxX - 0.12f, fMinY + 0.12f, 0));
                circlePositions.Add(new Vector3(fMaxX, fMinY + 1.35f, 0));
                circlePositions.Add(new Vector3(fMaxX, fMaxY - 1.35f, 0));
                circlePositions.Add(new Vector3(fMaxX - 0.12f, fMaxY - 0.12f, 0));
                break;
            case 9:
                circlePositions.Add(new Vector3(fMaxX, fMaxY - 1.35f, 0));
                circlePositions.Add(new Vector3(fMinX + 0.12f, fMinY + 0.12f, 0));
                circlePositions.Add(new Vector3(fMaxX - 0.12f, fMaxY - 0.12f, 0));
                circlePositions.Add(new Vector3(fMaxX - 0.12f, fMinY + 0.12f, 0));
                circlePositions.Add(new Vector3(fMinX, fMinY + 1.35f, 0));
                circlePositions.Add(new Vector3(fMinX, fMaxY - 1.35f, 0));
                circlePositions.Add(new Vector3(fMaxX, fMinY + 1.35f, 0));
                circlePositions.Add(new Vector3(fMinX + 0.12f, fMaxY - 0.12f, 0));

                circlePositions.Add(new Vector3(0, fMaxY, 0));
                break;
        }

        //triangles form a hellacannon at the center of the tank
        switch (myTriangles.Count)
        {
            case 1:
                trianglePositions.Add(new Vector3(0, 0, 0));
                break;
            case 2:
                trianglePositions.Add(new Vector3(-0.33f, 0, 0));
                trianglePositions.Add(new Vector3(0.33f, 0, 0));
                break;
            case 3:
                trianglePositions.Add(new Vector3(0.33f, -0.33f, 0));
                trianglePositions.Add(new Vector3(-0.33f, -0.33f, 0));
                trianglePositions.Add(new Vector3(0, 0.4f, 0));
                break;
            case 4:
                trianglePositions.Add(new Vector3(0, -0.05f, 0));
                trianglePositions.Add(new Vector3(0.63f, -0.5f, 0));
                trianglePositions.Add(new Vector3(-0.63f, -0.5f, 0));
                trianglePositions.Add(new Vector3(0, 0.6f, 0));
                break;
                
            case 5:

                trianglePositions.Add(new Vector3(0.63f, -0.5f, 0));
                trianglePositions.Add(new Vector3(-0.63f, -0.5f, 0));
                trianglePositions.Add(new Vector3(0, -0.05f, 0));
                trianglePositions.Add(new Vector3(0.63f, 0.5f, 0));
                trianglePositions.Add(new Vector3(-0.63f, 0.5f, 0));
                break;

            case 6:
                trianglePositions.Add(new Vector3(0.63f, -0.5f, 0));
                trianglePositions.Add(new Vector3(-0.63f, -0.5f, 0));
                trianglePositions.Add(new Vector3(0, -0.5f, 0));
                trianglePositions.Add(new Vector3(-0.3f, -0.1f, 0));
                trianglePositions.Add(new Vector3(0.3f, -0.1f, 0));
                trianglePositions.Add(new Vector3(0, 0.4f, 0));
                break;

            case 7:
                trianglePositions.Add(new Vector3(0, 0.4f, 0));
                trianglePositions.Add(new Vector3(-0.3f, -0.1f, 0));
                trianglePositions.Add(new Vector3(0.3f, -0.1f, 0));
                trianglePositions.Add(new Vector3(0.63f, -0.5f, 0));
                trianglePositions.Add(new Vector3(0, 0.8f, 0));
                trianglePositions.Add(new Vector3(-0.63f, -0.5f, 0));
                trianglePositions.Add(new Vector3(0, -0.5f, 0));
                break;

            case 8:

                //three the middle
                trianglePositions.Add(new Vector3(0.63f, -0.2f, 0));
                trianglePositions.Add(new Vector3(-0.63f, -0.2f, 0));
                trianglePositions.Add(new Vector3(0, -0.2f, 0));

                //two below
                trianglePositions.Add(new Vector3(-0.3f, -0.6f, 0));
                trianglePositions.Add(new Vector3(0.3f, -0.6f, 0));

                //two above
                trianglePositions.Add(new Vector3(-0.3f, 0.2f, 0));
                trianglePositions.Add(new Vector3(0.3f, 0.2f, 0));

                //pointy top
                trianglePositions.Add(new Vector3(0, 0.8f, 0));
                break;

            case 9:

                //three peak once
                trianglePositions.Add(new Vector3(0.75f, -0.2f, 0));
                trianglePositions.Add(new Vector3(-0.75f, -0.2f, 0));
                trianglePositions.Add(new Vector3(0, 0.0f, 0));

                //one tippy top
                trianglePositions.Add(new Vector3(0, 1.4f, 0));

                //two below
                trianglePositions.Add(new Vector3(-0.3f, -0.6f, 0));
                trianglePositions.Add(new Vector3(0.3f, -0.6f, 0));

                //three peak 2
                trianglePositions.Add(new Vector3(0.75f, 0.6f, 0));
                trianglePositions.Add(new Vector3(-0.75f, 0.6f, 0));
                trianglePositions.Add(new Vector3(0,0.8f, 0));

                break;
        }
    }

    public void GetTriangleOffsets(ref List<Vector3> squarePositions, ref List<Vector3> circlePositions, ref List<Vector3> trianglePositions)
    {
        //triangles form the base of the Jet
        switch (myTriangles.Count)
        {
            case 1:
                trianglePositions.Add(new Vector3(0, 0, 0));
                break;
            case 2:
                trianglePositions.Add(new Vector3(0, 0, 0)); // base
                trianglePositions.Add(new Vector3(0, 1.2f, 0)); // nose cone
                break;
            case 3:
                trianglePositions.Add(new Vector3(0, 0, 0)); // base
                trianglePositions.Add(new Vector3(-0.5f, -0.75f, 0)); // side arms 1l
                trianglePositions.Add(new Vector3(0.5f, -0.75f, 0)); // side arms 1r
                break;
            case 4:
                trianglePositions.Add(new Vector3(0, 0, 0)); // base
                trianglePositions.Add(new Vector3(0, 1.2f, 0)); // nose cone
                trianglePositions.Add(new Vector3(-0.5f, -0.75f, 0)); // side arms 1l
                trianglePositions.Add(new Vector3(0.5f, -0.75f, 0)); // side arms 1r
                break;
            case 5:
                trianglePositions.Add(new Vector3(0, 0, 0)); // base
                trianglePositions.Add(new Vector3(0.5f, -0.75f, 0)); // side arms 1r
                trianglePositions.Add(new Vector3(-0.5f, -0.75f, 0)); // side arms 1l
                trianglePositions.Add(new Vector3(1f, -1.25f, 0)); // side arms 2r
                trianglePositions.Add(new Vector3(-1f, -1.25f, 0)); // side arms 2l
                break;
            case 6:
                trianglePositions.Add(new Vector3(0, 0, 0)); // base
                trianglePositions.Add(new Vector3(0, 1.2f, 0)); // nose cone
                trianglePositions.Add(new Vector3(-1f, -1.25f, 0)); // side arms 2l
                trianglePositions.Add(new Vector3(-0.5f, -0.75f, 0)); // side arms 1l
                trianglePositions.Add(new Vector3(1f, -1.25f, 0)); // side arms 2r
                trianglePositions.Add(new Vector3(0.5f, -0.75f, 0)); // side arms 1r
                break;
            case 7:
                trianglePositions.Add(new Vector3(0, 0, 0)); // base
                trianglePositions.Add(new Vector3(-0.5f, -0.75f, 0)); // side arms 1l
                trianglePositions.Add(new Vector3(0.5f, -0.75f, 0)); // side arms 1r
                trianglePositions.Add(new Vector3(-1.5f, -1.75f, 0)); // side arms 3l
                trianglePositions.Add(new Vector3(1.5f, -1.75f, 0)); // side arms 3r
                trianglePositions.Add(new Vector3(-1f, -1.25f, 0)); // side arms 2l
                trianglePositions.Add(new Vector3(1f, -1.25f, 0)); // side arms 2r
                break;
            case 8:
                trianglePositions.Add(new Vector3(0, 0, 0)); // base
                trianglePositions.Add(new Vector3(0, 1.2f, 0)); // nose cone
                trianglePositions.Add(new Vector3(-0.5f, -0.75f, 0)); // side arms 1l
                trianglePositions.Add(new Vector3(0.5f, -0.75f, 0)); // side arms 1r
                trianglePositions.Add(new Vector3(-1f, -1.25f, 0)); // side arms 2l
                trianglePositions.Add(new Vector3(1f, -1.25f, 0)); // side arms 2r
                trianglePositions.Add(new Vector3(-1.5f, -1.75f, 0)); // side arms 3l
                trianglePositions.Add(new Vector3(1.5f, -1.75f, 0)); // side arms 3r
                break;
            case 9:
                trianglePositions.Add(new Vector3(0, 0, 0)); // base
                trianglePositions.Add(new Vector3(-1f, -1.25f, 0)); // side arms 2l
                trianglePositions.Add(new Vector3(1f, -1.25f, 0)); // side arms 2r
                
                trianglePositions.Add(new Vector3(-0.75f, 0.6f, 0)); // side arm front L
                trianglePositions.Add(new Vector3(0.75f, 0.6f, 0)); // side arm front R

                trianglePositions.Add(new Vector3(-1.9f, -1.05f, 0)); // side arms 3l
                trianglePositions.Add(new Vector3(1.9f, -1.05f, 0)); // side arms 3r

                trianglePositions.Add(new Vector3(-0.5f, -0.75f, 0)); // side arms 1l
                trianglePositions.Add(new Vector3(0.5f, -0.75f, 0)); // side arms 1r
                break;
        }

        //measure extents 
        float fMinX = 0.0f;
        float fMaxX = 0.0f;
        float fMinY = 0.0f;
        float fMaxY = 0.0f;

        for (int t = 0; t < trianglePositions.Count; t++)
        {
            Vector3 v = trianglePositions[t];
            if (v.x < fMinX)
                fMinX = v.x;
            if (v.x > fMaxX)
                fMaxX = v.x;
            if (v.y < fMinY)
                fMinY = v.y;
            if (v.y > fMaxY)
                fMaxY = v.y;

        }

        //push out the extents a touch to give room for the spheres
        fMinX -= 0.75f;
        fMaxX += 0.75f;
        fMinY -= 0.75f;
        fMaxY += 0.75f;

        //add squares. Square offsets are from the turret.
        switch (mySquares.Count)
        {
            case 1:
                squarePositions.Add(new Vector3(0, 3.0f, 0)); //center of arc
                break;
            case 2:
                squarePositions.Add(new Vector3(-0.35f, 3.0f, 0)); //split center
                squarePositions.Add(new Vector3(0.35f, 3.0f, 0)); //split center
                break;
            case 3:
                squarePositions.Add(new Vector3(0, 3.0f, 0)); //center of arc
                squarePositions.Add(new Vector3(-0.7f, 2.75f, 0)); //split center 1 L 
                squarePositions.Add(new Vector3(0.7f, 2.75f, 0)); //split center 1 R
                break;
            case 4:
                squarePositions.Add(new Vector3(-0.35f, 3.0f, 0)); //split center L 
                squarePositions.Add(new Vector3(0.35f, 3.0f, 0)); //split center  R
                squarePositions.Add(new Vector3(-1.05f, 2.75f, 0)); //split center 2 L 
                squarePositions.Add(new Vector3(1.05f, 2.75f, 0)); //split center 2  R
                break;
            case 5:
                squarePositions.Add(new Vector3(0, 3.0f, 0)); //center of arc
                squarePositions.Add(new Vector3(-0.7f, 2.75f, 0)); //split center 1 L 
                squarePositions.Add(new Vector3(0.7f, 2.75f, 0)); //split center 1 R
                squarePositions.Add(new Vector3(-1.4f, 2.5f, 0)); //split center 2 L 
                squarePositions.Add(new Vector3(1.4f, 2.5f, 0)); //split center 2 R
                break;
            case 6:
                squarePositions.Add(new Vector3(-0.35f, 3.0f, 0)); //split center L 
                squarePositions.Add(new Vector3(0.35f, 3.0f, 0)); //split center  R
                squarePositions.Add(new Vector3(-1.05f, 2.75f, 0)); //split center 2 L 
                squarePositions.Add(new Vector3(1.05f, 2.75f, 0)); //split center 2  R
                squarePositions.Add(new Vector3(-1.75f, 2.75f, 0)); //split center 3 L 
                squarePositions.Add(new Vector3(1.75f, 2.75f, 0)); //split center 3  R
                break;
            case 7:
                squarePositions.Add(new Vector3(0, 3.0f, 0)); //center of arc
                squarePositions.Add(new Vector3(-0.7f, 2.75f, 0)); //split center 1 L 
                squarePositions.Add(new Vector3(0.7f, 2.75f, 0)); //split center 1 R
                squarePositions.Add(new Vector3(-1.4f, 2.5f, 0)); //split center 2 L 
                squarePositions.Add(new Vector3(1.4f, 2.5f, 0)); //split center 2 R
                squarePositions.Add(new Vector3(-2.1f, 2.25f, 0)); //split center 3 L 
                squarePositions.Add(new Vector3(2.1f, 2.25f, 0)); //split center 3 R
                break;
            case 8:
                squarePositions.Add(new Vector3(-0.35f, 3.0f, 0)); //split center L 
                squarePositions.Add(new Vector3(0.35f, 3.0f, 0)); //split center  R
                squarePositions.Add(new Vector3(-1.05f, 2.75f, 0)); //split center 2 L 
                squarePositions.Add(new Vector3(1.05f, 2.75f, 0)); //split center 2  R
                squarePositions.Add(new Vector3(-1.75f, 2.5f, 0)); //split center 3 L 
                squarePositions.Add(new Vector3(1.75f, 2.5f, 0)); //split center 3  R
                squarePositions.Add(new Vector3(-2.45f, 2.25f, 0)); //split center 4 L 
                squarePositions.Add(new Vector3(2.45f, 2.25f, 0)); //split center 4  R
                break;
            case 9:
                squarePositions.Add(new Vector3(0, 3.0f, 0)); //center of arc
                squarePositions.Add(new Vector3(-0.7f, 2.75f, 0)); //split center 1 L 
                squarePositions.Add(new Vector3(0.7f, 2.75f, 0)); //split center 1 R
                squarePositions.Add(new Vector3(-1.4f, 2.5f, 0)); //split center 2 L 
                squarePositions.Add(new Vector3(1.4f, 2.5f, 0)); //split center 2 R
                squarePositions.Add(new Vector3(-2.1f, 2.25f, 0)); //split center 3 L 
                squarePositions.Add(new Vector3(2.1f, 2.25f, 0)); //split center 3 R
                squarePositions.Add(new Vector3(-2.8f, 2.0f, 0)); //split center 4 L 
                squarePositions.Add(new Vector3(2.8f, 2.0f, 0)); //split center 4  R
                break;
        }

        //spheres behind the jet, must go faster
        switch (myCircles.Count)
        {
            case 1:
                circlePositions.Add(new Vector3(0, fMinY, 0));
                break;
            case 2:
                circlePositions.Add(new Vector3(-0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY, 0));
                break;
            case 3:
                circlePositions.Add(new Vector3(-0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0.0f, fMinY-0.2f, 0));
                break;
            case 4:
                circlePositions.Add(new Vector3(-0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(-0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0.3f, fMinY - 0.2f, 0));
                break;
            case 5:
                circlePositions.Add(new Vector3(-0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0.0f, fMinY-0.2f, 0));
                circlePositions.Add(new Vector3(-0.3f, fMinY - 0.4f, 0));
                circlePositions.Add(new Vector3(0.3f, fMinY - 0.4f, 0));
                break;
            case 6:
                circlePositions.Add(new Vector3(-0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(-0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(-0.2f, fMinY -0.4f, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY -0.4f, 0));

                break;
            case 7:
                circlePositions.Add(new Vector3(-0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(-0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(-0.2f, fMinY -0.4f, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY -0.4f, 0));
                break;
            case 8:
                circlePositions.Add(new Vector3(-0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0, fMinY, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(-0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(-0.2f, fMinY -0.4f, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY -0.4f, 0));

                break;
            case 9:
                circlePositions.Add(new Vector3(-0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(0, fMinY, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY, 0));
                circlePositions.Add(new Vector3(-0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0.3f, fMinY - 0.2f, 0));
                circlePositions.Add(new Vector3(0.0f, fMinY -0.6f, 0));
                circlePositions.Add(new Vector3(-0.2f, fMinY -0.4f, 0));
                circlePositions.Add(new Vector3(0.2f, fMinY -0.4f, 0));

                break;
        }
    }

}
