from typing import OrderedDict


def parse_manifest(manifest):
    """
    Parses a ballot manifest.
    Identifiers are not necessarily unique *across* batches.

    Input
    -----
    a ballot manifest in the syntax described above

    Returns
    -------
    an ordered dict containing batch ID (key) and ballot identifiers within
    the batch, either from sequential enumeration or from the given labels.
    """
    ballot_manifest_dict = OrderedDict()
    for i in manifest:
        # assert that the entry is a string with a comma in it
        # pull out batch label
        (batch, val) = i.split(",")
        batch = batch.strip()
        val = val.strip()
        if batch in ballot_manifest_dict.keys():
            raise ValueError('batch is listed more than once')
        else:
            ballot_manifest_dict[batch] = []

        # parse what comes after the batch label
        if '(' in val:     # list of identifiers
            # TO DO: use regex to remove )(
            val = val[1:-1] # strip out the parentheses
            ballot_manifest_dict[batch] += [int(num) for num in val.split()]
        elif ':' in val:   # range of identifiers
            limits = val.split(':')
            ballot_manifest_dict[batch] += list(range(int(limits[0]), \
                                             int(limits[1])+1))
        else:  # this should be an integer number of ballots
            try:
                ballot_manifest_dict[batch] += list(range(1, int(val)+1))
            except:
                print('malformed row in ballot manifest:\n\t', i)
    return ballot_manifest_dict