def wait_for_package_sync(
    ctx, opts, owner, repo, slug, wait_interval, skip_errors, attempts=3
):
    """Wait for a package to synchronise (or fail)."""
    # pylint: disable=too-many-locals
    attempts -= 1
    click.echo()
    label = "Synchronising %(package)s:" % {"package": click.style(slug, fg="green")}

    status_str = "Waiting"
    stage_str = None

    def display_status(current):
        """Display current sync status."""
        # pylint: disable=unused-argument
        if not stage_str:
            return status_str
        return click.style(
            "%(status)s / %(stage)s" % {"status": status_str, "stage": stage_str},
            fg="cyan",
        )

    context_msg = "Failed to synchronise file!"
    with handle_api_exceptions(
        ctx, opts=opts, context_msg=context_msg, reraise_on_error=skip_errors
    ):
        last_progress = 0
        with click.progressbar(
            length=100,
            label=label,
            fill_char=click.style("#", fg="green"),
            empty_char=click.style("-", fg="red"),
            item_show_func=display_status,
        ) as pb:
            while True:
                res = get_package_status(owner, repo, slug)
                ok, failed, progress, status_str, stage_str, reason = res
                delta = progress - last_progress
                if delta > 0:
                    last_progress = progress
                    pb.update(delta)
                if ok or failed:
                    break
                time.sleep(wait_interval)

    if ok:
        click.secho("Package synchronised successfully!", fg="green")
        return

    click.secho(
        "Package failed to synchronise during stage: %(stage)s"
        % {"stage": click.style(stage_str or "Unknown", fg="yellow")},
        fg="red",
    )

    if reason:
        click.secho(
            "Reason given: %(reason)s" % {"reason": click.style(reason, fg="yellow")},
            fg="red",
        )

        # pylint: disable=fixme
        # FIXME: The API should communicate "no retry" fails
        if "package should be deleted" in reason and attempts > 1:
            click.secho(
                "This is not recoverable, so stopping further attempts!", fg="red"
            )
            click.echo()
            attempts = 0

    if attempts + 1 > 0:
        # Show attempts upto and including zero attempts left
        click.secho(
            "Attempts left: %(left)s (%(action)s)"
            % {
                "left": click.style(six.text_type(attempts), bold=True),
                "action": "trying again" if attempts > 0 else "giving up",
            }
        )
        click.echo()

    if attempts > 0:
        from .resync import resync_package

        resync_package(
            ctx=ctx,
            opts=opts,
            owner=owner,
            repo=repo,
            slug=slug,
            skip_errors=skip_errors,
        )

        wait_for_package_sync(
            ctx=ctx,
            opts=opts,
            owner=owner,
            repo=repo,
            slug=slug,
            wait_interval=wait_interval,
            skip_errors=skip_errors,
            attempts=attempts,
        )
    else:
        ctx.exit(1)