# from mathutils import *
from math import *
import bpy


def angle_to_length(angle: float, target: float = 1.0) -> float:
    """
    Converts input angle to distance between two points in imaginary isosceles triangle with default angle of 180deg(!).
    The distance is clamped to the target value.

    :param angle: Input angle (in radians)
    :type angle: float
    :param target: Desired distance between end points, defaults to 1.0
    :type target: float, optional
    :return: The distance between two points
    :rtype: float
    """
    if angle > 0:
        return (target * 0.5 * sin(pi - angle)) / sin(angle * 0.5)  # School trigonometry
    else:
        return target


def half_angle_to_length(angle: float, target: float = 1.0) -> float:
    """
    Converts input angle to distance between two points in imaginary isosceles triangle with default angle of 90deg.
    The distance is clamped to the target value.

    :param angle: Input angle (in radians)
    :type angle: float
    :param target: Desired distance between end points, defaults to 1.0
    :type target: float, optional
    :return: The distance between two points
    :rtype: float
    """
    side = sqrt(pow(target, 2) * 0.5)  # Length of imaginary triangle's side
    angle = abs(pi * 0.5 - angle)  # Default angle is 90deg
    return (side * sin(angle)) / sin((pi - angle) * 0.5)


def half_elbow_compensation(angle: float) -> float:
    side = sqrt(pow(pi * 0.25, 2) * 0.5)  # Length of imaginary triangle's side
    angle = abs(angle)
    final_angle = (side * sin(angle)) / sin((pi - angle) * 0.5)  # Width of imaginary triangle's base
    return sqrt(pow(tan(final_angle), 2) + 1) - 1  # What the fuck??


def compensated_elbow_corner(frame: float, offset: float = 0.125) -> float:
    # min(0.125, 0.125 * tan(acos(1 - frame / 180)))
    c_angle = acos(1 - frame / 180)
    return min(offset, offset * tan(c_angle))


def compensated_elbow_crease(frame: float, offset_1: float = 0.0625, offset_2: float = 0.125) -> float:
    # min(0.0625, 0.0625 * tan(acos(1 - frame / 180))) + 0.125 * tan(max(acos(1 - frame / 180) - pi / 4, 0))
    c_angle = acos(1 - frame / 180)
    first_stage = min(offset_1, offset_1 * tan(c_angle))
    second_stage = (tan(max(c_angle - pi / 4, 0)) * offset_2)
    return first_stage + second_stage


def compensated_elbow_corner_2(frame: float, offset: float = 0.125) -> float:
    # 0.125 * (sqrt(pow(tan(acos(1 - frame / 180)), 2) + 1) - 1)
    c_angle = acos(1 - frame / 180)
    return offset * (sqrt(pow(tan(c_angle), 2) + 1) - 1)


bpy.app.driver_namespace["angle_to_length"] = angle_to_length
bpy.app.driver_namespace["half_angle_to_length"] = half_angle_to_length
bpy.app.driver_namespace["half_elbow_compensation"] = half_elbow_compensation
bpy.app.driver_namespace["compensated_elbow_corner"] = compensated_elbow_corner
bpy.app.driver_namespace["compensated_elbow_corner_2"] = compensated_elbow_corner_2
bpy.app.driver_namespace["compensated_elbow_crease"] = compensated_elbow_crease
