import warnings


def prep_manifest(manifest, N_cards, n_cvrs):
    """
    Prepare a hart ballot manifest (read as a pandas dataframe) for sampling.
    The manifest may have cards that do not contain the contest, but every listed CVR
    is assumed to have a corresponding card in the manifest.

    If the number of CVRs n_cvrs is less than the number of cards that might contain the contest,
    N_cards, an additional "phantom" batch is added to the manifest to make up the difference.

    Parameters:
    ----------
    manifest : dataframe
        should contain the columns
           'Container', 'Tabulator', 'Batch Name', 'Number of Ballots'

    Returns:
    --------
    manifest with additional column for cumulative cards and, if needed, an additional
    batch for any phantom cards

    manifest_cards : the total number of cards in the manifest
    phantom_cards : the number of phantom cards required
    """
    cols = ['Container', 'Tabulator', 'Batch Name', 'Number of Ballots']
    assert set(cols).issubset(manifest.columns), "missing columns"
    manifest_cards = manifest['Number of Ballots'].sum()
    if n_cvrs < N_cards:
        warnings.warn('The CVR list does not account for every card cast in the contest; adding a phantom batch to the manifest')
        r = {'Container': None, 'Tabulator': 'phantom', 'Batch Name': 1, \
             'Number of Ballots': N_cards-n_cvrs}
        manifest = manifest.append(r, ignore_index = True)
    manifest['cum_cards'] = manifest['Number of Ballots'].cumsum()
    for c in ['Container', 'Tabulator', 'Batch Name']:
        manifest[c] = manifest[c].astype(str)
    return manifest, manifest_cards, N_cards - n_cvrs