from ..grid import symbols

class GridRenderer(object):
    """Class that renders a grid in some human-consumable form.
    
    This base class's methods result in a flat string of symbols, but it's easy
    to create a more useful rendering by just overriding a few methods.
    """

    def render_grid(self, grid):
        """Renders the entire grid.  Code on the outside probably only needs to
        call this.

        Returns a string.
        """
        parts = []

        parts.append(self.before_grid(grid))
        for idx, row in enumerate(grid.rows):
            if idx and idx % grid.box_height == 0:
                parts.append(self.inside_grid(grid))
            parts.append(self.render_row(row))
        parts.append(self.after_grid(grid))

        return ''.join(parts)

    def render_row(self, row):
        """Renders a single row."""
        parts = []

        parts.append(self.before_row(row))
        for idx, cell in enumerate(row.cells):
            if idx and idx % row.grid.box_width == 0:
                parts.append(self.inside_row(row))
            parts.extend(self.render_cell(cell))
        parts.append(self.after_row(row))

        return ''.join(parts)

    def render_cell(self, cell):
        """Renders a single cell."""
        return ''.join([
            self.before_cell(cell),
            self.inside_cell(cell),
            self.after_cell(cell),
        ])


    def before_grid(self, grid):
        """Content prepended before the entire grid."""
        return self.inside_grid(grid)

    def inside_grid(self, grid):
        """Content inserted within the grid, between boxes."""
        return ''

    def after_grid(self, grid):
        """Content appended after the entire grid."""
        return self.inside_grid(grid)


    def before_row(self, row):
        """Content prepended before each row."""
        return self.inside_row(row)

    def inside_row(self, row):
        """Content inserted within each row, between boxes."""
        return ''

    def after_row(self, row):
        """Content appended after each row.

        Note that newlines are not assumed; you must provide one if you want
        one included in the rendering.
        """

        return self.inside_row(row)


    def before_cell(self, cell):
        """Content prepended before each cell in a row."""
        return ''

    def inside_cell(self, cell):
        """Content used to represent the actual cell value."""
        if cell.solved:
            return symbols[cell.value]
        else:
            return '.'

    def after_cell(self, cell):
        """Content appended after each row in a cell."""
        return ''

