<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def _generate_report(ret, setup):
    '''
    Generate report dictionary
    '''

    retdata = ret.get('return', {})

    sorted_data = sorted(
        retdata.items(),
        key=lambda s: s[1].get('__run_num__', 0)
    )

    total = 0
    failed = 0
    changed = 0
    duration = 0.0

    # gather stats
    for _, data in sorted_data:
        if not data.get('result', True):
            failed += 1
        total += 1

        try:
            duration += float(data.get('duration', 0.0))
        except ValueError:
            pass

        if data.get('changes', {}):
            changed += 1

    unchanged = total - failed - changed

    log.debug('highstate total: %s', total)
    log.debug('highstate failed: %s', failed)
    log.debug('highstate unchanged: %s', unchanged)
    log.debug('highstate changed: %s', changed)

    # generate report if required
    if setup.get('report_everything', False) or \
       (setup.get('report_changes', True) and changed != 0) or \
       (setup.get('report_failures', True) and failed != 0):

        report = [
            {'stats': [
                {'total': total},
                {'failed': failed, '__style__': 'failed'},
                {'unchanged': unchanged, '__style__': 'unchanged'},
                {'changed': changed, '__style__': 'changed'},
                {'duration': duration}
            ]},
            {'job': [
                {'function': ret.get('fun', '')},
                {'arguments': ret.get('fun_args', '')},
                {'jid': ret.get('jid', '')},
                {'success': ret.get('success', True)},
                {'retcode': ret.get('retcode', 0)}
            ]},
            {'states': _generate_states_report(sorted_data)}
        ]

        if failed:
            function = setup.get('failure_function', None)
        else:
            function = setup.get('success_function', None)

        if function:
            func_result = __salt__[function]()
            report.insert(
                0,
                {'extra': [{function: _dict_to_name_value(func_result)}]}
            )

    else:
        report = []

    return report, failed