import numpy as np
import pytest

import holoviews as hv
from holoviews.core.options import AbbreviatedException
from holoviews.testing import assert_data_equal

from .test_plot import TestMPLPlot, mpl_renderer


class TestErrorBarPlot(TestMPLPlot):
    ###########################
    #    Styling mapping      #
    ###########################

    def test_errorbars_color_op(self):
        errorbars = hv.ErrorBars(
            [
                (0, 0, 0.1, 0.2, "#000000"),
                (0, 1, 0.2, 0.4, "#FF0000"),
                (0, 2, 0.6, 1.2, "#00FF00"),
            ],
            vdims=["y", "perr", "nerr", "color"],
        ).opts(color="color")
        plot = mpl_renderer.get_plot(errorbars)
        artist = plot.handles["artist"]
        assert_data_equal(
            artist.get_edgecolors(), np.array([[0, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1]])
        )

    def test_errorbars_color_op_update(self):
        errorbars = hv.HoloMap(
            {
                0: hv.ErrorBars(
                    [
                        (0, 0, 0.1, 0.2, "#000000"),
                        (0, 1, 0.2, 0.4, "#FF0000"),
                        (0, 2, 0.6, 1.2, "#00FF00"),
                    ],
                    vdims=["y", "perr", "nerr", "color"],
                ),
                1: hv.ErrorBars(
                    [
                        (0, 0, 0.1, 0.2, "#FF0000"),
                        (0, 1, 0.2, 0.4, "#00FF00"),
                        (0, 2, 0.6, 1.2, "#0000FF"),
                    ],
                    vdims=["y", "perr", "nerr", "color"],
                ),
            }
        ).opts(color="color")
        plot = mpl_renderer.get_plot(errorbars)
        artist = plot.handles["artist"]
        assert_data_equal(
            artist.get_edgecolors(), np.array([[0, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1]])
        )
        plot.update((1,))
        assert_data_equal(
            artist.get_edgecolors(), np.array([[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1]])
        )

    def test_errorbars_linear_color_op(self):
        errorbars = hv.ErrorBars(
            [(0, 0, 0.1, 0.2, 0), (0, 1, 0.2, 0.4, 1), (0, 2, 0.6, 1.2, 2)],
            vdims=["y", "perr", "nerr", "color"],
        ).opts(color="color")
        msg = "ValueError: Mapping a continuous or categorical dimension to a color"
        with pytest.raises(AbbreviatedException, match=msg):
            mpl_renderer.get_plot(errorbars)

    def test_errorbars_categorical_color_op(self):
        errorbars = hv.ErrorBars(
            [(0, 0, 0.1, 0.2, "A"), (0, 1, 0.2, 0.4, "B"), (0, 2, 0.6, 1.2, "C")],
            vdims=["y", "perr", "nerr", "color"],
        ).opts(color="color")
        msg = "ValueError: Mapping a continuous or categorical dimension to a color"
        with pytest.raises(AbbreviatedException, match=msg):
            mpl_renderer.get_plot(errorbars)

    def test_errorbars_line_color_op(self):
        errorbars = hv.ErrorBars(
            [
                (0, 0, 0.1, 0.2, "#000000"),
                (0, 1, 0.2, 0.4, "#FF0000"),
                (0, 2, 0.6, 1.2, "#00FF00"),
            ],
            vdims=["y", "perr", "nerr", "color"],
        ).opts(edgecolor="color")
        plot = mpl_renderer.get_plot(errorbars)
        artist = plot.handles["artist"]
        assert_data_equal(
            artist.get_edgecolors(), np.array([[0, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1]])
        )

    def test_errorbars_alpha_op(self):
        errorbars = hv.ErrorBars([(0, 0, 0), (0, 1, 0.2), (0, 2, 0.7)], vdims=["y", "alpha"]).opts(
            alpha="alpha"
        )
        msg = 'ValueError: Mapping a dimension to the "alpha" style'
        with pytest.raises(AbbreviatedException, match=msg):
            mpl_renderer.get_plot(errorbars)

    def test_errorbars_line_width_op(self):
        errorbars = hv.ErrorBars(
            [(0, 0, 0.1, 0.2, 1), (0, 1, 0.2, 0.4, 4), (0, 2, 0.6, 1.2, 8)],
            vdims=["y", "perr", "nerr", "line_width"],
        ).opts(linewidth="line_width")
        plot = mpl_renderer.get_plot(errorbars)
        artist = plot.handles["artist"]
        assert artist.get_linewidths() == [1, 4, 8]

    def test_errorbars_line_width_op_update(self):
        errorbars = hv.HoloMap(
            {
                0: hv.ErrorBars(
                    [(0, 0, 0.1, 0.2, 1), (0, 1, 0.2, 0.4, 4), (0, 2, 0.6, 1.2, 8)],
                    vdims=["y", "perr", "nerr", "line_width"],
                ),
                1: hv.ErrorBars(
                    [(0, 0, 0.1, 0.2, 2), (0, 1, 0.2, 0.4, 6), (0, 2, 0.6, 1.2, 4)],
                    vdims=["y", "perr", "nerr", "line_width"],
                ),
            }
        ).opts(linewidth="line_width")
        plot = mpl_renderer.get_plot(errorbars)
        artist = plot.handles["artist"]
        assert artist.get_linewidths() == [1, 4, 8]
        plot.update((1,))
        assert artist.get_linewidths() == [2, 6, 4]
