import json
import hashlib


def _generate_etag(etag_data, etag_schema=None, extra_data=None):
    """Generate an ETag from data

    etag_data: Data to use to compute ETag
    etag_schema: Schema to dump data with before hashing
    extra_data: Extra data to add before hashing

    Typically, extra_data is used to add pagination metadata to the hash. It is
    not dumped through the Schema.
    """
    if etag_schema is None:
        raw_data = etag_data
    else:
        if isinstance(etag_schema, type):
            etag_schema = etag_schema()
        raw_data = etag_schema.dump(etag_data)[0]
    if extra_data:
        raw_data = (raw_data, extra_data)
    # flask's json.dumps is needed here
    # as vanilla json.dumps chokes on lazy_strings
    data = json.dumps(raw_data, sort_keys=True)
    return hashlib.sha1(bytes(data, 'utf-8')).hexdigest()