from visidata import VisiData, vd, Column, Sheet, Fanout, asyncthread

@Column.api
def setWidth(self, w):
    if self.width != w:
        vd.addUndo(setattr, self, '_width', self.width)
        if self.sheet:
            self.sheet.setModified()
    self._width = w


@Column.api
def toggleWidth(self, width):
    'Change column width to either given `width` or default value.'
    if self.width != width:
        self.width = width
    else:
        self.width = int(self.sheet.options.default_width)


@Sheet.api
def resize_cols_max(sheet, cols):
    'Resize all *cols* to max width as a group; if all already at max, reset all to default.'
    rows = sheet.visibleRows
    maxwidths = {c: c.getMaxWidth(rows) for c in cols}
    if all(c.width == maxwidths[c] for c in cols):
        default = int(sheet.options.default_width)
        for c in cols:
            c.setWidth(default)
    else:
        for c in cols:
            c.setWidth(maxwidths[c])


@Column.api
def toggleMultiline(self):
    if self.height == 1:
        self.height = self.sheet.options.default_height
    else:
        self.height = 1

@VisiData.api
def unhide_cols(vd, cols, rows):
    'sets appropriate width if column was either hidden (0) or unseen (None)'
    for c in cols:
        c.setWidth(abs(c.width or 0) or c.getMaxWidth(rows))

@VisiData.api
def hide_col(vd, col):
    if not col: vd.fail("no columns to hide")
    sheet = col.sheet
    # hiding rightmost visible col: keep cursor on new rightmost instead of stranding on first hidden
    keepcursor = sheet and not col.hidden and col in sheet.visibleCols \
                 and sheet.cursorVisibleColIndex >= len(sheet.visibleCols)-1
    col.hide()
    if keepcursor:
        sheet.cursorRight(-1)

@Sheet.api
@asyncthread
def hide_uniform_cols(sheet):
    if len(sheet.rows) < 2:
        return
    idx = sheet.cursorVisibleColIndex
    for i, col in enumerate(sheet.visibleCols):
        vals = (col.getTypedValue(r) for r in sheet.rows)
        first = next(vals)
        if all(v == first for v in vals):
            vd.status(f'hide {col.name} with value: {col.getDisplayValue(sheet.rows[0])}')
            if i <= idx:
                sheet.cursorRight(-1)
            col.hide()

Sheet.addCommand('_', 'resize-col-max', 'if cursorCol: cursorCol.toggleWidth(cursorCol.getMaxWidth(visibleRows))', 'toggle width of current column between full and default width')
Sheet.addCommand('z_', 'resize-col-input', 'width = int(input("set width= ", value=cursorCol.width)); cursorCol.setWidth(width)', 'adjust width of current column to N')
Sheet.addCommand('g_', 'resize-cols-max', 'sheet.resize_cols_max(visibleCols)', 'set widths of all visible columns to full width; if all already full, reset to default')
Sheet.addCommand('gz_', 'resize-cols-input', 'width = int(input("set width= ", value=cursorCol.width)); Fanout(visibleCols).setWidth(width)', 'adjust widths of all visible columns to N')

Sheet.addCommand('-', 'hide-col', 'hide_col(cursorCol)', 'hide the current column')
Sheet.addCommand('z-', 'resize-col-half', 'width = cursorCol.width if cursorCol.width is not None else options.default_width; cursorCol.setWidth(width//2)', 'reduce width of current column by half')
Sheet.addCommand('g-', 'hide-uniform-cols', 'sheet.hide_uniform_cols()', 'hide any column that has multiple rows but only one distinct value')

Sheet.addCommand('gv', 'unhide-cols', 'unhide_cols(columns, visibleRows)', 'unhide all hidden columns on current sheet')
Sheet.addCommand('v', 'toggle-multiline', 'for c in visibleCols: c.toggleMultiline()', 'toggle multiline display')
Sheet.addCommand('zv', 'resize-height-input', 'Fanout(visibleCols).height=int(input("set height for all columns to: ", value=max(c.height for c in sheet.visibleCols)))', 'resize row height to N')
Sheet.addCommand('gzv', 'resize-height-max', 'h=calc_height(cursorRow, {}, maxheight=windowHeight-1); vd.status(f"set height for all columns to {h}"); Fanout(visibleCols).height=h', 'resize row height to max height needed to see this row')

vd.addMenuItems('''
    Column > Hide > Hide > hide-col
    Column > Hide > Hide uniform > hide-uniform-cols
    Column > Hide > Unhide all > unhide-cols
    Column > Resize > half width > resize-col-half
    Column > Resize > current column width to max > resize-col-max
    Column > Resize > current column width to N > resize-col-input
    Column > Resize > all columns width to max > resize-cols-max
    Column > Resize > all columns width to N > resize-cols-input
    Row > Resize > height to N > resize-height-input
    Row > Resize > height to max > resize-height-max
    View > Toggle display > multiline > toggle-multiline
''')
