from enum import Enum
from ppc_robot_lib.utils.types import Color
class HiddenDimensionOptions(Enum):
    SHOW_ALL = 1
    """Show data from hidden columns and rows."""
    SKIP_HIDDEN = 2
    """Skip data in hidden columns and rows."""
class StackType(Enum):
    NOT_STACKED = 1
    """The chart is not stacked."""
    STACKED = 2
    """Chart is stacked using raw values. Maximum for each X value is determined by sum of values in each series."""
    STACKED_PERCENT = 3
    """Chart is stacked using normalized value. Maximum for each X value is always 100%."""
[docs]
class AxisPosition(Enum):
    LEFT = 1
    """Left axis."""
    RIGHT = 2
    """Right axis.""" 
[docs]
class LineType(Enum):
    SOLID = 1
    """Solid line."""
    DOTTED = 2
    """Dotted line."""
    MEDIUM_DASHED = 3
    """Dashed line, medium dashes."""
    LONG_DASHED = 4
    """Dashed line, long dashes.""" 
[docs]
class LineStyle:
    def __init__(self, width: int, line_type: LineType = LineType.SOLID):
        """
        :param width: Line width in pixels.
        :param line_type: Line type.
        """
        self.width = width
        self.line_type = line_type 
[docs]
class EmbeddedChart:
    """
    Represents a chart that is embedded directly in the sheet.
    A chart specification must be set. The used specification determines the type of chart that will be created.
    """
    def __init__(self, spec: 'ChartSpec', width: int = 600, height: int = 400, data_sheet_id: int | None = None):
        """
        :param spec: Chart type with parameters
        :param width: Width in pixels.
        :param height: Height in pixels.
        :param data_sheet_id: ID of sheet with data that will be used for the graph.
        """
        self.spec = spec
        self.width = width
        self.height = height
        self.data_sheet_id = data_sheet_id 
class AxisSpec:
    """
    Axis description.
    """
    def __init__(self, title: str):
        """
        :param title: Axis label.
        """
        self.title = title
class SeriesSpec:
    def __init__(self, column: str, color: Color, line_style: LineStyle = None, axis: AxisPosition = AxisPosition.LEFT):
        self.column = column
        self.color = color
        self.line_style = line_style if line_style is not None else LineStyle(2)
        self.axis = axis
[docs]
class ChartSpec:
    """
    Represents specification of a chart type. Do not use directly, but use any of the sub-classes:
    * :py:class:`ppc_robot_lib.output.charts.LineChart`
    """
    def __init__(
        self,
        title: str,
        subtitle: str = '',
        hidden_dimensions: HiddenDimensionOptions = HiddenDimensionOptions.SHOW_ALL,
    ):
        self.title = title
        self.subtitle = subtitle
        self.hidden_dimensions = hidden_dimensions 
[docs]
class LineChart(ChartSpec):
    """
    Represents a line chart.
    """
    def __init__(
        self,
        title: str,
        subtitle: str,
        domain_column: str,
        bottom_axis_title: str = '',
        left_axis_title: str = '',
        right_axis_title: str | None = None,
        hidden_dimensions: HiddenDimensionOptions = HiddenDimensionOptions.SHOW_ALL,
        line_smoothing: bool = False,
        stacked: StackType = StackType.NOT_STACKED,
        use_column_headers: bool = True,
    ):
        """
        :param title: Chart title.
        :param subtitle: Chart subtitle.
        :param domain_column: Name of the column that will be used as the label of the X axis.
        :param bottom_axis_title: Description of the X axis.
        :param left_axis_title: Description of the main Y axis on the left.
        :param right_axis_title: Optional description of the secondary Y axis on the right. If not given, right Y axis
            is not created.
        :param hidden_dimensions: How to handle hidden columns and rows.
        :param line_smoothing: Enable line-smoothing?
        :param use_column_headers: Use column names as series labels?
        """
        super().__init__(title, subtitle, hidden_dimensions)
        self.domain_column = domain_column
        self.bottom_axis = AxisSpec(bottom_axis_title)
        self.left_axis = AxisSpec(left_axis_title)
        self.right_axis = AxisSpec(right_axis_title) if right_axis_title is not None else None
        self.series: list[SeriesSpec] = []
        self.line_smoothing = line_smoothing
        self.stacked = stacked
        self.use_column_headers = use_column_headers
[docs]
    def add_series(
        self, column: str, color: Color, line_style: LineStyle = None, axis: AxisPosition = AxisPosition.LEFT
    ) -> 'LineChart':
        """
        :param column: Name of the column that should be used as data for the series.
        :param color: Line color.
        :param line_style: Line style, if not given, solid line is used.
        :param axis: What axis to use to plot the data.
        """
        self.series.append(SeriesSpec(column, color, line_style, axis))
        return self