"""DuckieDai Law of Cosines for TI-84 Plus CE Python."""

from math import sqrt, cos, acos, radians, 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 positive_number(prompt):
    """Require a positive number."""
    while True:
        try:
            value = float(input(prompt))

            if value > 0 and value < 1e100:
                return value

        except ValueError:
            pass

        print("Enter a number above 0.")


def angle_number(prompt):
    """Require an angle between 0 and 180 degrees."""
    while True:
        try:
            value = float(input(prompt))

            if value > 0 and value < 180:
                return value

        except ValueError:
            pass

        print("Angle must be")
        print("between 0 and 180.")


def valid_triangle(a, b, c):
    """Check triangle inequality."""
    return (
        a + b > c and
        a + c > b and
        b + c > a
    )


def safe_acos(value):
    """Protect against tiny rounding errors."""
    if value > 1:
        value = 1

    if value < -1:
        value = -1

    return acos(value)


def show_answer(name, value, unit):
    print()
    print("ANSWER")
    print(name + " = " + str(value))
    print(unit)


def main():
    duckiedai_intro("LAW OF COSINES")

    print("LAW OF COSINES")
    print()
    print("c^2 = a^2 + b^2")
    print("      -2ab*cos(C)")
    print()
    print("What do you need?")
    print()
    print("1. Side a")
    print("2. Side b")
    print("3. Side c")
    print("4. Angle A")
    print("5. Angle B")
    print("6. Angle C")
    print()

    choice = input("Choose 1-6: ")

    print()

    # ==========================================
    # 1. SOLVE SIDE a
    #
    # a^2 = b^2 + c^2 - 2bc*cos(A)
    # ==========================================

    if choice == "1":

        b = positive_number("Side b: ")
        c = positive_number("Side c: ")
        A = angle_number("Angle A (deg): ")

        value = (
            b ** 2 +
            c ** 2 -
            2 * b * c * cos(radians(A))
        )

        if value <= 0:
            print("No valid triangle.")

        else:
            a = sqrt(value)

            print()
            print("Using:")
            print("a^2=b^2+c^2")
            print("   -2bc*cos(A)")

            show_answer(
                "a",
                a,
                "units"
            )

    # ==========================================
    # 2. SOLVE SIDE b
    #
    # b^2 = a^2 + c^2 - 2ac*cos(B)
    # ==========================================

    elif choice == "2":

        a = positive_number("Side a: ")
        c = positive_number("Side c: ")
        B = angle_number("Angle B (deg): ")

        value = (
            a ** 2 +
            c ** 2 -
            2 * a * c * cos(radians(B))
        )

        if value <= 0:
            print("No valid triangle.")

        else:
            b = sqrt(value)

            print()
            print("Using:")
            print("b^2=a^2+c^2")
            print("   -2ac*cos(B)")

            show_answer(
                "b",
                b,
                "units"
            )

    # ==========================================
    # 3. SOLVE SIDE c
    #
    # c^2 = a^2 + b^2 - 2ab*cos(C)
    # ==========================================

    elif choice == "3":

        a = positive_number("Side a: ")
        b = positive_number("Side b: ")
        C = angle_number("Angle C (deg): ")

        value = (
            a ** 2 +
            b ** 2 -
            2 * a * b * cos(radians(C))
        )

        if value <= 0:
            print("No valid triangle.")

        else:
            c = sqrt(value)

            print()
            print("Using:")
            print("c^2=a^2+b^2")
            print("   -2ab*cos(C)")

            show_answer(
                "c",
                c,
                "units"
            )

    # ==========================================
    # ANGLES REQUIRE ALL 3 SIDES
    # ==========================================

    elif choice == "4" or \
         choice == "5" or \
         choice == "6":

        a = positive_number("Side a: ")
        b = positive_number("Side b: ")
        c = positive_number("Side c: ")

        if not valid_triangle(a, b, c):

            print()
            print("INVALID TRIANGLE")
            print()
            print("These sides cannot")
            print("form a triangle.")

        # ======================================
        # 4. SOLVE ANGLE A
        #
        # cos(A) =
        # (b^2+c^2-a^2)/(2bc)
        # ======================================

        elif choice == "4":

            value = (
                b ** 2 +
                c ** 2 -
                a ** 2
            ) / (2 * b * c)

            A = degrees(
                safe_acos(value)
            )

            print()
            print("Using:")
            print("cos(A)=")
            print("(b^2+c^2-a^2)")
            print("/(2bc)")

            show_answer(
                "A",
                A,
                "degrees"
            )

        # ======================================
        # 5. SOLVE ANGLE B
        # ======================================

        elif choice == "5":

            value = (
                a ** 2 +
                c ** 2 -
                b ** 2
            ) / (2 * a * c)

            B = degrees(
                safe_acos(value)
            )

            print()
            print("Using:")
            print("cos(B)=")
            print("(a^2+c^2-b^2)")
            print("/(2ac)")

            show_answer(
                "B",
                B,
                "degrees"
            )

        # ======================================
        # 6. SOLVE ANGLE C
        # ======================================

        else:

            value = (
                a ** 2 +
                b ** 2 -
                c ** 2
            ) / (2 * a * b)

            C = degrees(
                safe_acos(value)
            )

            print()
            print("Using:")
            print("cos(C)=")
            print("(a^2+b^2-c^2)")
            print("/(2ab)")

            show_answer(
                "C",
                C,
                "degrees"
            )

    else:
        print("Invalid choice.")

    print()
    print("DuckieDai says: done!")


# TI-Python imports the selected AppVar rather than
# setting __name__ to main.
main()
