using System;
using System.Collections.Generic;
using System.Text;
using HumanLikeBattleRobots.Graphic;
using HumanLikeBattleRobots.Data;

namespace HumanLikeBattleRobots.Logic
{
    enum MovingLeg { None, Left, Right }
    abstract class Legs
    {
        private float movingSpeed = 0;
        private float nextSpeed = 0;
        private float angularVelocity = 0;
        private bool isMoving = true;

        private Vec2f axisCenter;
        private Vec2f axisNormal;
        private Vec2f legNormal;

        private float rotationAngle = 0;

        private MovingLeg movingLeg = MovingLeg.Right;

        //настраиваемые для каждого дочернего класса параметры
        protected float axisLength = 70;
        protected Sprite leftLeg;
        protected Sprite rightLeg;
        protected double maxAngle = Math.PI / 6;
        protected float health;
        protected float maxHealth;

        public Vec2f Normal { get { return axisNormal; } }
        public float RotationAngle { get { return rotationAngle; } }

        public Legs(Vec2f centralPosition, float angle, List<List<Sprite>> sprites) //угол - в радианах!
        {
            axisCenter = centralPosition;
            axisNormal = new Vec2f(angle);
            legNormal = new Vec2f(angle);

            SetParams();

            sprites[leftLeg.Stage - 1].Add(leftLeg);
            sprites[rightLeg.Stage - 1].Add(rightLeg);
        }

        protected abstract void SetParams();

        public Vec2f AxisCenter { get {return axisCenter;} set {axisCenter = value;}}

        public float AxisAngle()
        {
            //return axisNormal.Rotate(Math.PI / 2).Angle360();
            return axisNormal.Angle360();
        }

        public float AngleBetween()
        {
            return axisNormal.AngleBetween(legNormal);
        }

        private Vec2f Corner(MovingLeg leg)
        {
            double angle = Math.PI/2;
            if (leg == MovingLeg.Left)
                angle = -angle;
            return axisCenter + axisNormal.Rotate(angle) * axisLength/2;
        }
        
        private MovingLeg HoldingLeg(MovingLeg leg)
        {
            if (leg == MovingLeg.Left)
                return MovingLeg.Right;
            else
                return MovingLeg.Left;
        }
    
        private void AxisMove(double delta, float speed)
        {

            float omega = speed / axisLength * health / maxHealth;
            float fi = omega * (float)delta;

            if (movingLeg == MovingLeg.Left)
                fi = -fi;

            rotationAngle = fi;

            legNormal = legNormal.Rotate(angularVelocity * health / maxHealth * (float)delta);
            // задали вектор оси
            Vec2f axisVector = Corner(movingLeg) - Corner(HoldingLeg(movingLeg));
            // повернули вектор
            axisVector = axisVector.Rotate(fi);
            // сместили центр координат
            axisCenter = Corner(HoldingLeg(movingLeg)) + axisVector / 2;
            // повернули нормаль
            axisNormal = axisNormal.Rotate(fi);

            // доводим ноги при остановке
            if (nextSpeed == 0 && axisNormal.AngleBetween(legNormal) < Math.PI/100)
            {
                movingSpeed = 0;
                rotationAngle = 0;
                axisNormal = legNormal;
            }

            //смена ног
            if (axisNormal.AngleBetween(legNormal) > maxAngle)
            {
                movingLeg = HoldingLeg(movingLeg);
                if (nextSpeed != 0)
                    movingSpeed = nextSpeed;
                axisNormal = axisNormal.Rotate(-fi + 0.001);
                //if (movingLeg == MovingLeg.Left)
                if (this is MyLegs && !GameManager.Mute)
                    Bass.Bass.BASS_SamplePlayEx(SoundResources.Clank, 0, 0, 40, 0, false);
                    //Bass.Bass.BASS_SamplePlay(SoundResources.Clank);  
            }
        }

        public void Move(float speed) //может быть отрицательной и положительной
        {
            isMoving = true;
            nextSpeed = speed;
        }

        public void Stop()
        {
            isMoving = false;
            nextSpeed = 0;
        }

        public void Rotate(float angularVelocity)
        {
            if (movingSpeed > 0)
                this.angularVelocity = -angularVelocity;
            else if (movingSpeed < 0)
                this.angularVelocity = angularVelocity;
            else
                this.angularVelocity = 0;
        }

        public void TakeDamage(float damage)
        {
            health -= damage;
            if (health < 0)
                health = 0;
        }

        public void Proceed(double delta)
        {
            if (movingSpeed != 0)
                AxisMove(delta, movingSpeed);
            if (isMoving && movingSpeed == 0)
                movingSpeed = nextSpeed;

            leftLeg.Position = Corner(MovingLeg.Left);
            rightLeg.Position = Corner(MovingLeg.Right);
            leftLeg.Angle = legNormal.Rotate(Math.PI / 2).Angle360();
            rightLeg.Angle = legNormal.Rotate(Math.PI / 2).Angle360();
        }
    }
}
