"""DuckieDai Work and Energy for TI-84 Plus CE Python."""

from math import cos, radians, 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):
    """Ask until a valid finite number is entered."""
    while True:
        try:
            value = float(input(prompt))

            if value > -1e100 and value < 1e100:
                return value

        except ValueError:
            pass

        print("Enter a valid number.")


def positive_number(prompt):
    """Ask until a positive finite number is entered."""
    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 show_answer(name, value, unit):
    input("Press enter for answer ")
    print("\n" * 6)
    print("ANSWER")
    print(name + " = " + str(value))
    print(unit)


def main():
    duckiedai_intro("WORK & ENERGY")

    print("WORK & ENERGY")
    print()
    print("1. Calculate Work")
    print("2. Kinetic Energy")
    print("3. Final speed")
    print("   from net work")
    print("4. Initial speed")
    print("   from net work")
    input("Press enter for more ")
    print("\n" * 6)
    print("5. Solve force")
    print("6. Solve distance")
    print("7. Solve angle")
    print()

    choice = input("Choose 1-7: ")

    print()

    # ==========================================
    # 1. WORK
    # W = F*d*cos(theta)
    # ==========================================

    if choice == "1":

        force = number("Force (N): ")
        distance = positive_number("Distance (m): ")
        angle = number("Angle (degrees): ")

        work = (
            force *
            distance *
            cos(radians(angle))
        )

        print()
        print("Using:")
        print("W = F*d*cos(theta)")
        print()
        print("W = " + str(force) +
              " x " + str(distance))
        print("x cos(" + str(angle) + ")")

        show_answer(
            "W",
            work,
            "joules"
        )


    # ==========================================
    # 2. KINETIC ENERGY
    # KE = 0.5*m*v^2
    # ==========================================

    elif choice == "2":

        mass = positive_number("Mass (kg): ")
        velocity = number("Velocity (m/s): ")

        ke = (
            0.5 *
            mass *
            velocity ** 2
        )

        print()
        print("Using:")
        print("KE = 0.5*m*v^2")
        print()
        print("KE = 0.5 x " +
              str(mass) + " x")
        print(str(velocity) + "^2")

        show_answer(
            "KE",
            ke,
            "joules"
        )


    # ==========================================
    # 3. FINAL SPEED FROM NET WORK
    #
    # W = KEf - KEi
    #
    # vf = sqrt(vi^2 + 2W/m)
    # ==========================================

    elif choice == "3":

        mass = positive_number("Mass (kg): ")
        vi = number("Initial speed: ")
        work = number("Net work (J): ")

        inside = (
            vi ** 2 +
            (2 * work / mass)
        )

        if inside < 0:

            print()
            print("No real final speed.")
            print("Check the values.")
            print()
            print("Negative work may")
            print("stop the object.")

        else:

            vf = sqrt(inside)

            print()
            print("Using:")
            print("W = KEf - KEi")
            print()
            print("Rearranged:")
            print("vf=sqrt(vi^2+2W/m)")

            show_answer(
                "Final speed",
                vf,
                "m/s"
            )


    # ==========================================
    # 4. INITIAL SPEED FROM NET WORK
    #
    # vi = sqrt(vf^2 - 2W/m)
    # ==========================================

    elif choice == "4":

        mass = positive_number("Mass (kg): ")
        vf = number("Final speed: ")
        work = number("Net work (J): ")

        inside = (
            vf ** 2 -
            (2 * work / mass)
        )

        if inside < 0:

            print()
            print("No real initial speed.")
            print("Check the values.")

        else:

            vi = sqrt(inside)

            print()
            print("Using:")
            print("W = KEf - KEi")
            print()
            print("Rearranged:")
            print("vi=sqrt(vf^2-2W/m)")

            show_answer(
                "Initial speed",
                vi,
                "m/s"
            )


    # ==========================================
    # 5. SOLVE FORCE
    #
    # F = W / (d*cos(theta))
    # ==========================================

    elif choice == "5":

        work = number("Work (J): ")
        distance = positive_number("Distance (m): ")
        angle = number("Angle (degrees): ")

        c = cos(radians(angle))

        if abs(c) < 0.0000001:

            print()
            print("Cannot solve force.")
            print("cos(angle) is zero.")

        else:

            force = (
                work /
                (distance * c)
            )

            print()
            print("Using:")
            print("W = F*d*cos(theta)")
            print()
            print("Rearranged:")
            print("F=W/(d*cos(theta))")

            show_answer(
                "F",
                force,
                "newtons"
            )


    # ==========================================
    # 6. SOLVE DISTANCE
    #
    # d = W / (F*cos(theta))
    # ==========================================

    elif choice == "6":

        work = number("Work (J): ")
        force = number("Force (N): ")
        angle = number("Angle (degrees): ")

        c = cos(radians(angle))

        denominator = force * c

        if abs(denominator) < 0.0000001:

            print()
            print("Cannot solve distance.")
            print("Check force/angle.")

        else:

            distance = (
                work /
                denominator
            )

            print()
            print("Using:")
            print("W = F*d*cos(theta)")
            print()
            print("Rearranged:")
            print("d=W/(F*cos(theta))")

            show_answer(
                "d",
                distance,
                "meters"
            )


    # ==========================================
    # 7. SOLVE ANGLE
    #
    # theta = acos(W / (F*d))
    # ==========================================

    elif choice == "7":

        work = number("Work (J): ")
        force = number("Force (N): ")
        distance = positive_number("Distance (m): ")

        denominator = force * distance

        if denominator == 0:

            print()
            print("Cannot solve angle.")

        else:

            ratio = work / denominator

            if ratio < -1 or ratio > 1:

                print()
                print("No real angle.")
                print("Check the values.")

            else:

                angle = degrees(
                    acos(ratio)
                )

                print()
                print("Using:")
                print("W = F*d*cos(theta)")
                print()
                print("Rearranged:")
                print("theta=acos(W/(F*d))")

                show_answer(
                    "theta",
                    angle,
                    "degrees"
                )

    else:

        print("Invalid choice.")

    print()
    print("DuckieDai says: done!")


# TI-Python imports the selected AppVar rather than
# setting __name__ to main.
main()
