import math


def quaternion_to_euler_list(quaternion:list, degrees = False, axis_qw=0, axis_front=1, axis_left=2, axis_up=3):
    """
    Returns the euler representation of a quaternion [qw, qi, qj, qk] into
        yaw     = [-pi, pi]
        pitch   = [-pi/2, pi/2]
        roll    = [-pi, pi]

    If the quaternion is not in the order [qw, qi, qj, qk], you can specify these variables to set the index of the dimension:
        - `axis_qw`     > Contains the scalar factor of the quaternion
        - `axis_front`  > Contains the axis indicating the POSITIVE-FRONT in the coordinate reference system
        - `axis_left`   > Contains the axis indicating the POSITIVE-LEFT in the coordinate reference system
        - `axis_up`     > Contains the axis indicating the POSITIVE-UP in the coordinate reference system

    Based on Eq 2.9 of the Technical report in: 
    https://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=08A583E84796E221D446200475B7841A?doi=10.1.1.468.5407&rep=rep1&type=pdf

    :param quaternion: Unit quaternion representation
    :type quaternion: list of length 4
    :return: [yaw, pitch, roll] in radians, or degrees if `degrees=True`
    :rtype: list of length 3
    """

    qr = quaternion[axis_qw]
    qi= quaternion[axis_front]
    qj = quaternion[axis_left]
    qk = quaternion[axis_up]

    # Squares of vector components to speed-up calculations
    sqi = qi*qi
    sqj = qj*qj
    sqk = qk*qk

    ### Euler angles
    # roll (x-axis rotation)
    sinr_cosp = 2 * (qr * qi + qj * qk)
    cosr_cosp = 1 - 2 * (sqi + sqj)
    roll = math.atan2(sinr_cosp, cosr_cosp)

    # pitch (y-axis rotation)
    sinp = 2 * (qr * qj - qk * qi)
    # Evaluates singularity at +/- 90 degrees to prevent GIMBAL LOCK. Happening at north/south pole.
    pitch = 0
    if (abs(sinp) >= 1):
        print("GIMBAL LOCK!! with quaternion", quaternion)
        pitch = math.copysign(math.pi / 2, sinp) # use 90 degrees if out of range
    else:
        pitch = math.asin(sinp)

    # yaw (z-axis rotation)
    siny_cosp = 2 * (qr * qk + qi * qj)
    cosy_cosp = 1 - 2 * (sqj + sqk)
    yaw = math.atan2(siny_cosp, cosy_cosp)

    # Transform from radians to degrees
    factor = 1
    if(degrees): ## CONVERT FROM RADIANS TO DEGREES
        factor = 180.0 / math.pi

    return [yaw*factor, pitch*factor, roll*factor]