"""DuckieDai Vector Angle for TI-84 Plus CE Python."""

from math import sqrt, acos, degrees


def duckiedai_intro(program_name, wait=True):
    """Show the reusable DuckieDai program opening."""
    title = program_name[:16]
    empty = 16 - len(title)
    left = empty // 2
    right = empty - left

    print("+----------------------+")
    print("|   " + " " * left + title + " " * right + "   |")
    print("|                      |")
    print("|       __             |")
    print("|   ___(o )>  quack!   |")
    print("|   \\ <_. )           |")
    print("|    `---'             |")
    print("|     by DuckieDai     |")
    print("+----------------------+")
    print("Loading...")

    if wait:
        input("Press enter to start ")
        print("\n" * 6)


def number(prompt):
    """Allow positive, negative, or zero values."""
    while True:
        try:
            value = float(input(prompt))

            if value > -1e100 and value < 1e100:
                return value

        except ValueError:
            pass

        print("Enter a valid number.")


def safe_acos(value):
    """Protect acos from floating-point rounding."""
    if value > 1:
        value = 1

    if value < -1:
        value = -1

    return acos(value)


def magnitude(x, y, z=0):
    """Return vector magnitude."""
    return sqrt(
        x ** 2 +
        y ** 2 +
        z ** 2
    )


def main():
    duckiedai_intro("VECTOR ANGLE")

    print("VECTOR DOT PRODUCT")
    print("& ANGLE")
    print()
    print("1. 2D vectors")
    print("2. 3D vectors")
    print()

    choice = input("Choose 1 or 2: ")

    print()

    # ==========================================
    # 2D VECTOR INPUT
    # ==========================================

    if choice == "1":

        print("VECTOR u")
        ux = number("ux: ")
        uy = number("uy: ")
        uz = 0

        print()
        print("VECTOR v")
        vx = number("vx: ")
        vy = number("vy: ")
        vz = 0

    # ==========================================
    # 3D VECTOR INPUT
    # ==========================================

    elif choice == "2":

        print("VECTOR u")
        ux = number("ux: ")
        uy = number("uy: ")
        uz = number("uz: ")

        print()
        print("VECTOR v")
        vx = number("vx: ")
        vy = number("vy: ")
        vz = number("vz: ")

    else:

        print("Invalid choice.")
        print()
        print("DuckieDai says: done!")
        return

    # ==========================================
    # VECTOR MAGNITUDES
    # ==========================================

    mag_u = magnitude(
        ux, uy, uz
    )

    mag_v = magnitude(
        vx, vy, vz
    )

    # Angle is undefined if either vector
    # has zero magnitude.

    if mag_u == 0 or mag_v == 0:

        print()
        print("ANGLE UNDEFINED")
        print()
        print("A zero vector has")
        print("no direction.")
        print()
        print("DuckieDai says: done!")
        return

    # ==========================================
    # DOT PRODUCT
    #
    # u dot v =
    # ux*vx + uy*vy + uz*vz
    # ==========================================

    dot = (
        ux * vx +
        uy * vy +
        uz * vz
    )

    # ==========================================
    # ANGLE
    #
    # cos(theta) =
    # dot / (|u|*|v|)
    # ==========================================

    cos_theta = (
        dot /
        (mag_u * mag_v)
    )

    theta = degrees(
        safe_acos(cos_theta)
    )

    # ==========================================
    # RESULTS
    # ==========================================

    print()
    print("Using:")
    print("u dot v /")
    print("(|u|*|v|)")
    print()

    print("DOT PRODUCT")
    print("u dot v =")
    print(str(dot))
    print()

    print("MAGNITUDES")
    print("|u| = " + str(mag_u))
    print("|v| = " + str(mag_v))
    print()

    print("cos(theta) =")
    print(str(cos_theta))
    print()

    print("ANGLE")
    print("theta =")
    print(str(theta))
    print("degrees")
    print()

    # ==========================================
    # CLASSIFY ANGLE
    # ==========================================

    tolerance = 0.0000001

    if abs(dot) < tolerance:

        print("Vectors are")
        print("PERPENDICULAR.")

    elif dot > 0:

        print("Angle is ACUTE.")

    else:

        print("Angle is OBTUSE.")

    print()
    print("DuckieDai says: done!")


# TI-Python imports the selected AppVar rather than
# setting __name__ to main.
main()
