from . import plots


def scatter_geo(
    x,
    y=None,
    x_range=None,
    y_range=None,
    add_interaction=True,
    color_palette=None,
    aggregate_col=None,
    aggregate_fn="count",
    point_size=1,
    point_shape="circle",
    pixel_shade_type="eq_hist",
    pixel_density=0.5,
    pixel_spread="dynspread",
    width=800,
    height=400,
    tile_provider="CARTODBPOSITRON",
    title="",
    timeout=1,
    **library_specific_params,
):
    """
    Parameters
    ----------

    x: str
        x-axis column name from the gpu dataframe
    y: str, default None
        y-axis column name from the gpu dataframe
    x_range: tuple, default(gpu_dataframe[x].min(), gpu_dataframe[x].max())
        (min, max) x-dimensions of the geo-scatter plot to be displayed
    y_range: tuple, default(gpu_dataframe[x].min(), gpu_dataframe[x].max())
        (min, max) x-dimensions of the geo-scatter plot to be displayed

    add_interaction: {True, False},  default True

    color_palette: bokeh.palettes or list of hex_color_codes, or list of color
                    names,  default inferno

    aggregate_col: str, default None
        Column from the gpu dataframe on which the aggregate_fn will be run on,
        if None, aggregate_fn is run on y-column.

    aggregate_fn: {'count', 'mean', 'max', 'min'},  default 'count'

    point_size: int, default 1
        Point size in the scatter plot.

    point_shape: str, default 'circle'
        Available options: circle, square, rect_vertical, rect_horizontal.

    pixel_shade_type: str, default 'eq_hist'
        The "how" parameter in datashader.transfer_functions.shade()
        function.
        Available options: eq_hist, linear, log, cbrt

    pixel_density: float, default 0.5
        A tuning parameter in [0, 1], with higher values giving more dense
        scatter plot.

    pixel_spread: str, default 'dynspread'
        dynspread: Spread pixels in an image dynamically based on the image
        density.
        spread: Spread pixels in an image.

    width: int,  default 800

    height: int,  default 400

    tile_provider: str, default 'CARTODBPOSITRON'
        Underlying map type.See
        https://bokeh.pydata.org/en/latest/docs/reference/tile_providers.html

    title: str,

        chart title

    timeout: int
        Determines the timeout after which the callback will
        process new events without the previous one having
        reported completion. Increase for very long running
        callbacks and if zooming feels laggy.

    **library_specific_params:
        additional library specific keyword arguments to be passed to the
        function

    Returns
    -------
    A cudashader geo-scatter plot.
    Type cuxfilter.charts.datashader.custom_extensions.InteractiveImage
    """
    return plots.ScatterGeo(
        x,
        y,
        x_range,
        y_range,
        add_interaction,
        color_palette,
        aggregate_col,
        aggregate_fn,
        point_size,
        point_shape,
        pixel_shade_type,
        pixel_density,
        pixel_spread,
        width,
        height,
        tile_provider,
        title,
        timeout,
        **library_specific_params,
    )


def scatter(
    x,
    y,
    x_range=None,
    y_range=None,
    add_interaction=True,
    color_palette=None,
    aggregate_col=None,
    aggregate_fn="count",
    point_size=1,
    point_shape="circle",
    pixel_shade_type="eq_hist",
    pixel_density=0.5,
    pixel_spread="dynspread",
    width=800,
    height=400,
    title="",
    timeout=1,
    **library_specific_params,
):
    """
    Parameters
    ----------

    x: str
        x-axis column name from the gpu dataframe
    y: str, default None
        y-axis column name from the gpu dataframe
    x_range: tuple, default(gpu_dataframe[x].min(), gpu_dataframe[x].max())
        (min, max) x-dimensions of the geo-scatter plot to be displayed
    y_range: tuple, default(gpu_dataframe[y].min(), gpu_dataframe[y].max())
        (min, max) x-dimensions of the geo-scatter plot to be displayed

    add_interaction: {True, False},  default True

    color_palette: bokeh.palettes or list of hex_color_codes, or list of
                   color names,  default inferno

    aggregate_col: str, default None
        column from the gpu dataframe on which the aggregate_fn will be run on,
        if None, aggregate_fn is run on y-column

    aggregate_fn: {'count', 'mean', 'max', 'min'},  default 'count'

    point_size: int, default 1
        Point size in the scatter plot.

    point_shape: str, default 'circle'
        Available options: circle, square, rect_vertical, rect_horizontal.

    pixel_shade_type: str, default 'eq_hist'
        The "how" parameter in datashader.transfer_functions.shade()
        function.
        Available options: eq_hist, linear, log, cbrt

    pixel_density: float, default 0.5
        A tuning parameter in [0, 1], with higher values giving more dense
        scatter plot.

    pixel_spread: str, default 'dynspread'
        dynspread: Spread pixels in an image dynamically based on the image
        density.
        spread: Spread pixels in an image.

    width: int,  default 800

    height: int,  default 400

    title: str,

        chart title

    timeout: int
        Determines the timeout after which the callback will
        process new events without the previous one having
        reported completion. Increase for very long running
        callbacks and if zooming feels laggy.

    **library_specific_params:
        additional library specific keyword arguments to be passed to the
        function

    Returns
    -------
    A cudashader scatter plot.
    Type cuxfilter.charts.datashader.custom_extensions.InteractiveImage
    """
    return plots.Scatter(
        x,
        y,
        x_range,
        y_range,
        add_interaction,
        color_palette,
        aggregate_col,
        aggregate_fn,
        point_size,
        point_shape,
        pixel_shade_type,
        pixel_density,
        pixel_spread,
        width,
        height,
        title,
        timeout,
        **library_specific_params,
    )


def heatmap(
    x,
    y,
    x_range=None,
    y_range=None,
    add_interaction=True,
    color_palette=None,
    aggregate_col=None,
    aggregate_fn="mean",
    point_size=10,
    point_shape="rect_vertical",
    width=800,
    height=400,
    title="",
    timeout=1,
    **library_specific_params,
):
    """
    Heatmap using default datashader.scatter plot with slight modifications.
    Added for better defaults. In theory, scatter directly can be used
    to generate the same.

    Parameters
    ----------

    x: str
        x-axis column name from the gpu dataframe
    y: str, default None
        y-axis column name from the gpu dataframe
    x_range: tuple, default(gpu_dataframe[x].min(), gpu_dataframe[x].max())
        (min, max) x-dimensions of the geo-scatter plot to be displayed
    y_range: tuple, default(gpu_dataframe[y].min(), gpu_dataframe[y].max())
        (min, max) x-dimensions of the geo-scatter plot to be displayed

    add_interaction: {True, False},  default True

    color_palette: bokeh.palettes or list of hex_color_codes, or
                   list of color names,  default inferno

    aggregate_col: str, default None
        column from the gpu dataframe on which the aggregate_fn will be run on,
        if None, aggregate_fn is run on y-column

    aggregate_fn: {'count', 'mean', 'max', 'min'},  default 'count'

    point_size: int, default 1
        Point size in the scatter plot.

    point_shape: str, default 'rect_vertical'
        Available options: circle, square, rect_vertical, rect_horizontal.

    pixel_density: float, default 0.5
        A tuning parameter in [0, 1], with higher values giving more dense
        scatter plot.

    pixel_spread: str, default 'dynspread'
        dynspread: Spread pixels in an image dynamically based on the image
        density.
        spread: Spread pixels in an image.

    width: int,  default 800

    height: int,  default 400

    title: str,

        chart title

    timeout: int
        Determines the timeout after which the callback will
        process new events without the previous one having
        reported completion. Increase for very long running
        callbacks and if zooming feels laggy.

    **library_specific_params:
        additional library specific keyword arguments to be passed to the
        function

    Returns
    -------
    A cudashader heatmap (scatter object).
    Type cuxfilter.charts.datashader.custom_extensions.InteractiveImage
    """
    return plots.Scatter(
        x,
        y,
        x_range,
        y_range,
        add_interaction,
        color_palette,
        aggregate_col,
        aggregate_fn,
        point_size,
        point_shape,
        "linear",
        1,
        "spread",
        width,
        height,
        title,
        timeout,
        **library_specific_params,
    )


def line(
    x,
    y,
    data_points=100,
    add_interaction=True,
    pixel_shade_type="linear",
    color=None,
    step_size=None,
    step_size_type=int,
    width=800,
    height=400,
    title="",
    timeout=1,
    **library_specific_params,
):
    """

    Parameters
    ----------

    x: str
        x-axis column name from the gpu dataframe
    y: str
        y-axis column name from the gpu dataframe
    x_range: tuple, default(gpu_dataframe[x].min(), gpu_dataframe[x].max())
        (min, max) x-dimensions of the geo-scatter plot to be displayed
    y_range: tuple, default(gpu_dataframe[y].min(), gpu_dataframe[y].max())
        (min, max) x-dimensions of the geo-scatter plot to be displayed

    add_interaction: {True, False},  default True

    pixel_shade_type: str, default 'linear'
        The "how" parameter in datashader.transfer_functions.shade()
        function.
        Available options: eq_hist, linear, log, cbrt

    color: str,  default #8735fb

    step_size: int, default None
        for the range_slider below the chart

    step_size_type: type, default int
        for the range_slider below the chart

    width: int,  default 800

    height: int,  default 400

    title: str,

        chart title

    timeout: int
        Determines the timeout after which the callback will
        process new events without the previous one having
        reported completion. Increase for very long running
        callbacks and if zooming feels laggy.

    **library_specific_params:
        additional library specific keyword arguments to be passed to the
        function

    Returns
    -------
    A cudashader scatter plot.
    Type cuxfilter.charts.datashader.custom_extensions.InteractiveImage
    """
    return plots.Line(
        x,
        y,
        data_points,
        add_interaction,
        pixel_shade_type,
        color,
        step_size,
        step_size_type,
        width,
        height,
        title,
        timeout,
        **library_specific_params,
    )


def stacked_lines(
    x,
    y,
    data_points=100,
    add_interaction=True,
    colors=[],
    step_size=None,
    step_size_type=int,
    width=800,
    height=400,
    title="",
    timeout=1,
    **library_specific_params,
):
    """
    stacked lines chart

    Parameters
    ----------

    x: str
        x-axis column name from the gpu dataframe
    y: list
        y-axis column names from the gpu dataframe for the stacked lines

    add_interaction: {True, False},  default True

    colors: list, default [#8735fb, #8735fb, ....]

    step_size: int, default None
        for the range_slider below the chart

    step_size_type: type, default int
        for the range_slider below the chart

    width: int,  default 800

    height: int,  default 400

    title: str,

        chart title

    timeout: int
        Determines the timeout after which the callback will
        process new events without the previous one having
        reported completion. Increase for very long running
        callbacks and if zooming feels laggy.

    **library_specific_params:
        additional library specific keyword arguments to be passed to the
        function

    Returns
    -------
    A cudashader stacked_lines plot.
    Type cuxfilter.charts.datashader.custom_extensions.InteractiveImage
    """
    if type(y) is not list or len(y) == 0:
        raise ValueError("y must be a list of atleast one column name")
    return plots.StackedLines(
        x,
        y,
        data_points,
        add_interaction,
        colors,
        step_size,
        step_size_type,
        width,
        height,
        title,
        timeout,
        **library_specific_params,
    )
