'Generate a Profile page
@param r: the S3Request instance
@param attr: controller attributes for the request'

def profile(self, r, **attr):

    tablename = self.tablename
    get_config = current.s3db.get_config
    widgets = get_config(tablename, 'profile_widgets')
    if (not widgets):
        if (r.representation not in ('dl', 'aadata')):
            redirect(r.url(method='read'))
        else:
            r.error(405, current.ERROR.BAD_METHOD)
    for (index, widget) in enumerate(widgets):
        widget['index'] = index
    if (r.representation == 'dl'):
        index = r.get_vars.get('update', None)
        if index:
            try:
                index = int(index)
            except ValueError:
                datalist = ''
            else:
                datalist = self._datalist(r, widgets[index], **attr)
        output = {'item': datalist}
    elif (r.representation == 'aadata'):
        index = r.get_vars.get('update', None)
        if index:
            try:
                index = int(index)
            except ValueError:
                datalist = ''
            else:
                datatable = self._datatable(r, widgets[index], **attr)
        return datatable
    else:
        title = get_config(tablename, 'profile_title')
        if (not title):
            try:
                title = r.record.name
            except:
                title = current.T('Profile    Page')
        elif callable(title):
            title = title(r)
        header = get_config(tablename, 'profile_header')
        if (not header):
            header = H2(title, _class='profile-header')
        elif callable(header):
            header = header(r)
        output = dict(title=title, header=header)
        update = get_config(tablename, 'profile_update')
        if update:
            editable = get_config(tablename, 'editable', True)
            authorised = self._permitted(method='update')
            if (authorised and editable):
                show = self.crud_string(tablename, 'title_update')
                hide = current.T('Hide    Form')
                form = self.update(r, **attr)['form']
            else:
                show = self.crud_string(tablename, 'title_display')
                hide = current.T('Hide    Details')
                form = self.read(r, **attr)['item']
            if (update == 'visible'):
                hidden = False
                label = hide
                (style_hide, style_show) = (None, 'display:none')
            else:
                hidden = True
                label = show
                (style_hide, style_show) = ('display:none', None)
            toggle = A(SPAN(label, data={'on': show, 'off': hide}), ICON('down', _style=style_show), ICON('up', _style=style_hide), data={'hidden': hidden}, _class='form-toggle    action-lnk')
            form.update(_style=style_hide)
            output['form'] = DIV(toggle, form, _class='profile-update')
        else:
            output['form'] = ''
        response = current.response
        rows = []
        append = rows.append
        row = None
        cols = get_config(tablename, 'profile_cols')
        if (not cols):
            cols = 2
        row_cols = 0
        for widget in widgets:
            w_type = widget['type']
            if (w_type == 'comments'):
                w = self._comments(r, widget, **attr)
            elif (w_type == 'datalist'):
                w = self._datalist(r, widget, **attr)
            elif (w_type == 'datatable'):
                w = self._datatable(r, widget, **attr)
            elif (w_type == 'form'):
                w = self._form(r, widget, **attr)
            elif (w_type == 'map'):
                w = self._map(r, widget, widgets, **attr)
            elif (w_type == 'report'):
                w = self._report(r, widget, **attr)
            elif (w_type == 'custom'):
                w = self._custom(r, widget, **attr)
            elif response.s3.debug:
                raise SyntaxError(('Unsupported    widget    type    %s' % w_type))
            else:
                continue
            if (row is None):
                row = DIV(_class='row    profile')
                row_cols = 0
            row.append(w)
            colspan = widget.get('colspan', 1)
            row_cols += colspan
            if (row_cols == cols):
                append(row)
                row = None
        if row:
            append(row)
        output['rows'] = rows
        response.view = self._view(r, 'profile.html')
    return output
