def view_selected_team_pokemon(team_id: int = Route(),
                               team_index: int = Route(min_int=1, max_int=6),
                               pokeapi_id: int = Route()):
    """
    Returns the pokemon view page for pokemon selected on the previous pokemon select page.
    """

    team = Team.query.get(team_id)
    # Check is to prevent users from accessing the endpoint by manually entering the url if it's not their team
    if current_user.is_authenticated and current_user.id == team.owner_id:
        form = ConfirmForm()
        pokemon_api_data = Pokemon.get_pokemon_data(pokeapi_id)
        ability_data = [
            Pokemon.get_pokemon_ability_data(ability["ability"]["url"])
            for ability in pokemon_api_data["abilities"]
        ]
        return render_template("pokemon_view.html",
                               data=[pokemon_api_data, ability_data],
                               form=form,
                               team=team,
                               team_id=team_id,
                               team_index=team_index,
                               pokeapi_id=pokeapi_id,
                               type="team-selected")
    else:
        flash("You do not have permission to change this pokemon.")
        return redirect(request.referrer)
def view_selected_pokemon(pokeapi_id):
    """
    Returns the pokedex entry page for the pokemon selected on the previous pokemon list page.
    """

    pokemon_api_data = Pokemon.get_pokemon_data(pokeapi_id)
    ability_data = [
        Pokemon.get_pokemon_ability_data(ability["ability"]["url"])
        for ability in pokemon_api_data["abilities"]
    ]
    return render_template("pokemon_view.html",
                           data=[pokemon_api_data, ability_data],
                           pokeapi_id=pokeapi_id,
                           type="pokedex")
def get_pokemon_move_list(team_id: int = Route(),
                          team_index: int = Route(min_int=1, max_int=6),
                          pokemon_move_index: int = Route(min_int=1,
                                                          max_int=4)):
    """
    Returns the move list page for a pokemon on a team.
    """

    team_pokemon = Teams_Pokemon.query.get((team_id, team_index))

    # Check is to prevent users from accessing the endpoint by manually entering the url if it's not their team
    if current_user.is_authenticated and current_user.id == team_pokemon.team.owner_id:

        # Get current move as the back button on the template will need a different url if the current move is empty
        current_move = Pokemon_Moves.query.filter_by(
            team_pokemon_id=team_pokemon.id,
            pokemon_move_index=pokemon_move_index).first()

        # Get the Pokemons currently learned moves so that they can be excluded from the move list
        move_set = Pokemon_Moves.query.filter_by(
            team_pokemon_id=team_pokemon.id).order_by(
                Pokemon_Moves.pokemon_move_index).all()
        move_list = Move.get_move_list(
            Pokemon.get_pokemon_data(team_pokemon.pokeapi_id), move_set)
        return render_template("move_select.html",
                               move_list=move_list,
                               team_pokemon=team_pokemon,
                               current_move=current_move,
                               team_id=team_id,
                               team_index=team_index,
                               pokemon_move_index=pokemon_move_index)
    else:
        flash("You do not have permission to change this move.")
        return redirect(request.referrer)
def get_view_pokemon_list():
    """
    Returns the pokemon list page for looking up a pokemons pokedex entry without needing to create a team.
    """

    api_data = Pokemon.get_pokedex_list()
    return render_template("pokemon_select.html",
                           data=api_data,
                           type="pokedex")
def view_team_pokemon(team_id: int = Route(),
                      team_index: int = Route(min_int=1, max_int=6)):
    """
    Returns the pokemon view page for a pokemon on a team.
    """

    form = RemovePokemonForm()
    team = Team.query.get(team_id)
    team_pokemon = Teams_Pokemon.query.get((team_id, team_index))

    # If pokemon slot is empty skip the pokemon view and go to the pokemon list page to select a pokemon
    if not team_pokemon:
        return redirect(
            url_for("pokemon.get_team_pokemon_list",
                    team_id=team_id,
                    team_index=team_index))
    else:
        pokemon_api_data = Pokemon.get_pokemon_data(team_pokemon.pokeapi_id)

        # Get the pokemons currently assigned moves and insert null entries for move slots that are empty
        move_set = Pokemon_Moves.query.filter_by(
            team_pokemon_id=team_pokemon.id).order_by(
                Pokemon_Moves.pokemon_move_index).all()
        move_set_dict = pokemon_moves_schema.dump(move_set)
        indices = [move.pokemon_move_index for move in move_set]
        for i in range(4):
            if i + 1 not in indices:
                move_set_dict.insert(i, None)

        ability_data = [
            Pokemon.get_pokemon_ability_data(ability["ability"]["url"])
            for ability in pokemon_api_data["abilities"]
        ]
        data = [pokemon_api_data, ability_data]
        return render_template("pokemon_view.html",
                               data=data,
                               form=form,
                               moves=move_set_dict,
                               team_pokemon=team_pokemon,
                               team=team,
                               team_id=team_id,
                               team_index=team_index,
                               type="team")
def get_team_pokemon_list(team_id: int = Route(),
                          team_index: int = Route(min_int=1, max_int=6)):
    """
    Returns the pokemon list page for a team pokemon slot.
    """

    team = Team.query.get(team_id)

    # Get current pokemon as the back button on the template will need a different url if the current pokemon is empty
    current_pokemon = Teams_Pokemon.query.get((team_id, team_index))

    # Check is to prevent users from accessing the endpoint by manually entering the url if it's not their team
    if current_user.is_authenticated and current_user.id == team.owner_id:
        api_data = Pokemon.get_pokedex_list()
        return render_template("pokemon_select.html",
                               data=api_data,
                               current_pokemon=current_pokemon,
                               team=team,
                               team_id=team_id,
                               team_index=team_index,
                               type="team")
    else:
        flash("You do not have permission to change this pokemon.")
        return redirect(request.referrer)
def seed_db():
    """
    Custom flask db command to seed tables with fake data for testing
    """

    users = []
    for i in range(5):
        user = User()
        user.username = f"Test User {i + 1}"
        user.email = f"test{i + 1}@test.com"
        user.password = bcrypt.generate_password_hash("123456").decode("utf-8")
        db.session.add(user)
        users.append(user)

    db.session.commit()

    team_list = []
    for i in range(10):
        team = Team()
        team.name = f"Team {i + 1}"

        # Make sure there is always at least 1 public/private team
        if i == 8:
            team.is_private = False
        elif i == 9:
            team.is_private = True
        else:
            team.is_private = random.choice([True, False])
        owner = random.choice(users)
        team.owner_id = owner.id
        owner.teams.append(team)
        team_list.append(team)

    db.session.commit()

    pokemon_list = []
    for team in team_list:
        number_of_pokemon = random.randint(0, 6)
        for i in range(number_of_pokemon):
            pokemon = Pokemon()
            pokemon.pokemon_id = random.randint(1, 898)
            pokemon.pokeapi_id = pokemon.pokemon_id
            pokemon.pokemon_name = f"Random Name {i + 1}"
            if pokemon.pokeapi_id not in [
                    pokemon.pokeapi_id for pokemon in pokemon_list
            ]:
                db.session.add(pokemon)
            pokemon_list.append(pokemon)

            team_pokemon = Teams_Pokemon()
            team_pokemon.team_id = team.id
            team_pokemon.team_index = i + 1
            team_pokemon.pokeapi_id = pokemon.pokemon_id
            team.team_pokemon.append(team_pokemon)

    db.session.commit()

    move_list = []
    for team in team_list:
        number_of_moves = random.randint(0, 4)
        for team_pokemon in team.team_pokemon:
            for i in range(number_of_moves):
                move = Move()
                move.move_id = random.randint(1, 826)
                move.move_name = f"Random Move {i + 1}"
                if move.move_id not in [move.move_id for move in move_list]:
                    db.session.add(move)
                move_list.append(move)

                pokemon_move = Pokemon_Moves()
                pokemon_move.team_pokemon_id = team_pokemon.id
                pokemon_move.pokeapi_id = team_pokemon.pokemon.pokeapi_id
                pokemon_move.pokemon_move_index = i + 1
                pokemon_move.move_id = move.move_id
                db.session.add(pokemon_move)

    db.session.commit()

    print("TABLES SEEDED")
def edit_team_slot_pokemon(team_id: int = Route(),
                           team_index: int = Route(min_int=1, max_int=6),
                           pokeapi_id: int = Route()):
    """
    Adds a new pokemon to a team or updates an existing pokemon, when updating all child entries are deleted.
    """

    team = Team.query.get(team_id)
    # Check is to prevent users from accessing the endpoint by manually entering the url if it's not their team
    if current_user.is_authenticated and current_user.id == team.owner_id:
        form = ConfirmForm()
        if form.validate_on_submit():

            # Create new entry if pokemon not already in database
            pokemon = Pokemon.query.get(pokeapi_id)
            if not pokemon:
                pokemon_api_data = Pokemon.get_pokemon_data(pokeapi_id)
                pokemon = Pokemon()
                pokemon.pokeapi_id = pokeapi_id
                pokemon.pokemon_id = int(
                    pokemon_api_data["species"]["url"].replace(
                        "https://pokeapi.co/api/v2/pokemon-species/",
                        "").replace("/", ""))
                pokemon.pokemon_name = pokemon_api_data["name"]
                db.session.add(pokemon)
                db.session.commit()

            # Create new entry if there is no existing team_pokemon for this team id and team index,
            # otherwise update the existing entry
            team_pokemon = Teams_Pokemon.query.filter_by(
                team_id=team_id, team_index=team_index).first()
            if not team_pokemon:
                new_team_pokemon = Teams_Pokemon()
                new_team_pokemon.team_id = team_id
                new_team_pokemon.team_index = team_index
                new_team_pokemon.pokeapi_id = pokeapi_id
                team.team_pokemon.append(new_team_pokemon)
            else:
                teams_pokemon = Teams_Pokemon.query.filter_by(
                    team_id=team_id, team_index=team_index)
                data = {
                    "team_id": team_id,
                    "team_index": team_index,
                    "pokeapi_id": pokemon.pokeapi_id
                }

                teams_pokemon.update(
                    teams_pokemon_schema.load(data, partial=True))

                # Delete the saved moves of the old pokemon
                pokemon_moves = Pokemon_Moves.query.filter_by(
                    team_pokemon_id=teams_pokemon[0].id)
                for move in pokemon_moves:
                    db.session.delete(move)

            db.session.commit()

            return redirect(
                url_for("pokemon.view_team_pokemon",
                        team_id=team_id,
                        team_index=team_index))
    else:
        flash("You do not have permission to change this pokemon.")
        return redirect(request.referrer)