"""DuckieDai Coulomb's Law for TI-84 Plus CE Python."""

from math import sqrt


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 or negative finite numbers."""
    while True:
        try:
            value = float(input(prompt))

            if value > -1e100 and value < 1e100:
                return value

        except ValueError:
            pass

        print("Enter a valid number.")


def nonzero_number(prompt):
    """Require a number other than zero."""
    while True:
        value = number(prompt)

        if value != 0:
            return value

        print("Value cannot be zero.")


def positive_number(prompt):
    """Require a number greater than zero."""
    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 force_type(q1, q2):
    """Tell whether two charges attract or repel."""
    if q1 * q2 < 0:
        return "ATTRACTIVE"
    else:
        return "REPULSIVE"


def main():
    duckiedai_intro("COULOMBS LAW")

    ke = 8.988e9

    print("COULOMB'S LAW")
    print()
    print("Formula:")
    print("Fe = ke*|q1*q2|/r^2")
    print()
    print("ke = 8.988E9")
    input("Press enter for menu ")
    print("\n" * 6)
    print()
    print("What do you need?")
    print()
    print("1. Electric force")
    print("2. Charge 1")
    print("3. Charge 2")
    print("4. Distance")
    print()

    choice = input("Choose 1-4: ")

    print()

    # ==========================================
    # 1. SOLVE ELECTRIC FORCE
    #
    # Fe = ke*|q1*q2|/r^2
    # ==========================================

    if choice == "1":

        q1 = nonzero_number("Charge 1 (C): ")
        q2 = nonzero_number("Charge 2 (C): ")
        r = positive_number("Distance (m): ")

        force = (
            ke * abs(q1 * q2) /
            (r ** 2)
        )

        print()
        print("Using:")
        print("Fe = ke*|q1*q2|/r^2")

        show_answer(
            "Fe",
            force,
            "newtons"
        )

        print()
        print("Force type:")
        print(force_type(q1, q2))

    # ==========================================
    # 2. SOLVE MAGNITUDE OF CHARGE 1
    #
    # |q1| = Fe*r^2 / (ke*|q2|)
    # ==========================================

    elif choice == "2":

        force = positive_number("Force (N): ")
        q2 = nonzero_number("Charge 2 (C): ")
        r = positive_number("Distance (m): ")

        q1 = (
            force * r ** 2 /
            (ke * abs(q2))
        )

        print()
        print("Using:")
        print("Fe = ke*|q1*q2|/r^2")
        print()
        print("Rearranged:")
        print("|q1| = Fe*r^2")
        print("       /(ke*|q2|)")

        show_answer(
            "|q1|",
            q1,
            "coulombs"
        )

        print()
        print("Note:")
        print("Force alone cannot")
        print("determine q1 sign.")

    # ==========================================
    # 3. SOLVE MAGNITUDE OF CHARGE 2
    #
    # |q2| = Fe*r^2 / (ke*|q1|)
    # ==========================================

    elif choice == "3":

        force = positive_number("Force (N): ")
        q1 = nonzero_number("Charge 1 (C): ")
        r = positive_number("Distance (m): ")

        q2 = (
            force * r ** 2 /
            (ke * abs(q1))
        )

        print()
        print("Using:")
        print("Fe = ke*|q1*q2|/r^2")
        print()
        print("Rearranged:")
        print("|q2| = Fe*r^2")
        print("       /(ke*|q1|)")

        show_answer(
            "|q2|",
            q2,
            "coulombs"
        )

        print()
        print("Note:")
        print("Force alone cannot")
        print("determine q2 sign.")

    # ==========================================
    # 4. SOLVE DISTANCE
    #
    # r = sqrt(ke*|q1*q2|/Fe)
    # ==========================================

    elif choice == "4":

        force = positive_number("Force (N): ")
        q1 = nonzero_number("Charge 1 (C): ")
        q2 = nonzero_number("Charge 2 (C): ")

        r = sqrt(
            ke * abs(q1 * q2) /
            force
        )

        print()
        print("Using:")
        print("Fe = ke*|q1*q2|/r^2")
        print()
        print("Rearranged:")
        print("r = sqrt(")
        print("ke*|q1*q2|/Fe)")

        show_answer(
            "r",
            r,
            "meters"
        )

        print()
        print("Force type:")
        print(force_type(q1, q2))

    else:
        print("Invalid choice.")

    print()
    print("DuckieDai says: done!")


# TI-Python imports the selected AppVar rather than
# setting __name__ to main.
main()
