"""PA3 Gift Swap.

A group signs up for a gift swap, and each person draws a name from a hat to
find out who they are buying a gift for. Nobody may draw their own name, and
no name may be drawn twice. The wish lists come from a file, and the program
writes one card per person telling them who to shop for and what that person
wished for.

Name: YOUR NAME
Date: THE DATE
"""

import random


def draw_name(giver: str, names: list[str], taken: set[str]) -> str:
    """Draw a name from the hat for one giver.

    Args:
        giver: The person drawing.
        names: Everyone in the swap, the giver included.
        taken: The names already drawn by other people.

    Returns:
        A name from names that is not the giver and not in taken. Draw it with
        random.choice(names), and draw again for as long as you get the
        giver's own name or one already taken. If no name is left to draw,
        return "" without drawing at all, or the loop would never end. Ex:
        draw_name("Ana", ["Ana", "Ben"], set()) returns "Ben", and
        draw_name("Ana", ["Ana", "Ben"], {"Ben"}) returns "".
    """
    pass


def sign_up() -> list[str]:
    """Ask for the names of everyone in the swap, until a blank line.

    Each name is read with input("Name (blank to finish): "). A name with
    anything other than letters in it is rejected by printing "Letters only,
    please." and a name already signed up is rejected by printing, Ex, "Ben is
    already signed up." Either way, ask again.

    Returns:
        The names signed up, in the order they were entered, with no name
        twice. Ex: if the user types Ana, Ben, Ben, B3n, Cal, and a blank
        line, the result is ["Ana", "Ben", "Cal"].
    """
    pass


def load_wishes(filename: str) -> dict[str, str]:
    """Read everyone's wish from a file.

    Each line of the file is a name and a wish separated by "|", such as
    "Ana | a good mystery novel". Spaces around the name and the wish are
    removed. Blank lines, lines that start with "#", and lines with an empty
    wish are skipped. If a name is listed twice, its first wish is kept.

    Args:
        filename: The path of the file to read.

    Returns:
        A new dictionary that maps each name to its wish. Ex: the line
        " Ben |  fuzzy socks " gives {"Ben": "fuzzy socks"}.
    """
    pass


def save_cards(filename: str, givers: list[str], receivers: list[str],
               wishes: dict[str, str]) -> None:
    """Write one card per giver to a file, one line each.

    A card is the giver's name in capital letters, then who they are buying
    for, then that person's wish, Ex "ANA: buy a gift for Ben. Wish: fuzzy
    socks". A wish longer than 20 characters is cut to its first 17 and
    "..." is added, and a person with no wish in the dictionary gets
    "Surprise them!" instead.

    Args:
        filename: The path of the file to write. It is replaced if it exists.
        givers: The people giving gifts.
        receivers: The person each giver drew, in the same order as givers.
        wishes: Each person's wish, as returned by load_wishes().
    """
    pass


if __name__ == "__main__":
    # Do not edit the main block. It runs the whole swap once every part works.
    random.seed(122)
    wishes = load_wishes("wishes.txt")
    print("Sign up for the gift swap!")
    names = sign_up()
    if len(names) < 2:
        print("A swap needs at least two people.")
    else:
        done = False
        while not done:
            givers = []
            receivers = []
            taken = set()
            done = True
            for giver in names:
                if done:
                    receiver = draw_name(giver, names, taken)
                    if receiver == "":
                        print(f"{giver} would draw their own name, so everyone draws again.")
                        done = False
                    else:
                        givers.append(giver)
                        receivers.append(receiver)
                        taken.add(receiver)
        save_cards("cards.txt", givers, receivers, wishes)
        print(f"Wrote {len(givers)} cards to cards.txt.")
