import numpy as np
import pandas as pd

import holoviews as hv
from holoviews.testing import assert_data_equal

from .test_plot import TestPlotlyPlot


class TestAreaPlot(TestPlotlyPlot):
    def test_area_to_zero_y(self):
        curve = hv.Area([1, 2, 3])
        state = self._get_plot_state(curve)
        assert_data_equal(state["data"][0]["x"], np.array([0, 1, 2]))
        assert_data_equal(state["data"][0]["y"], np.array([1, 2, 3]))
        assert state["data"][0]["mode"] == "lines"
        assert state["data"][0]["fill"] == "tozeroy"
        assert state["layout"]["yaxis"]["range"] == [0, 3]

    def test_area_to_zero_x(self):
        curve = hv.Area([1, 2, 3]).opts(invert_axes=True)
        state = self._get_plot_state(curve)
        assert_data_equal(state["data"][0]["x"], np.array([1, 2, 3]))
        assert_data_equal(state["data"][0]["y"], np.array([0, 1, 2]))
        assert state["data"][0]["mode"] == "lines"
        assert state["data"][0]["fill"] == "tozerox"
        assert state["layout"]["xaxis"]["range"] == [0, 3]
        assert state["layout"]["yaxis"]["range"] == [0, 2]
        assert state["layout"]["xaxis"]["title"]["text"] == "y"
        assert state["layout"]["yaxis"]["title"]["text"] == "x"

    def test_area_fill_between_ys(self):
        area = hv.Area([(0, 1, 0.5), (1, 2, 1), (2, 3, 2.25)], vdims=["y", "y2"])
        state = self._get_plot_state(area)
        assert_data_equal(state["data"][0]["y"], np.array([0.5, 1, 2.25]))
        assert state["data"][0]["mode"] == "lines"
        assert state["data"][0].get("fill", None) is None
        assert_data_equal(state["data"][1]["y"], np.array([1, 2, 3]))
        assert state["data"][1]["mode"] == "lines"
        assert state["data"][1]["fill"] == "tonexty"
        assert state["layout"]["yaxis"]["range"] == [0.5, 3]

    def test_area_fill_between_xs(self):
        area = hv.Area([(0, 1, 0.5), (1, 2, 1), (2, 3, 2.25)], vdims=["y", "y2"]).opts(
            invert_axes=True
        )
        state = self._get_plot_state(area)
        assert_data_equal(state["data"][0]["x"], np.array([0.5, 1, 2.25]))
        assert state["data"][0]["mode"] == "lines"
        assert state["data"][0].get("fill", None) is None
        assert_data_equal(state["data"][1]["x"], np.array([1, 2, 3]))
        assert state["data"][1]["mode"] == "lines"
        assert state["data"][1]["fill"] == "tonextx"
        assert state["layout"]["xaxis"]["range"] == [0.5, 3]
        assert state["layout"]["yaxis"]["range"] == [0, 2]

    def test_area_visible(self):
        curve = hv.Area([1, 2, 3]).opts(visible=False)
        state = self._get_plot_state(curve)
        assert state["data"][0]["visible"] is False

    def test_area_stack_vdims(self):
        df = pd.DataFrame({"x": [1, 2, 3], "y_1": [1, 2, 3], "y_2": [6, 4, 2], "y_3": [8, 1, 2]})
        overlay = hv.Overlay(
            [hv.Area(df, kdims="x", vdims=col, label=col) for col in ["y_1", "y_2", "y_3"]]
        )
        plot = hv.Area.stack(overlay)
        baselines = [np.array([0, 0, 0]), np.array([1.0, 2.0, 3.0]), np.array([7.0, 6.0, 5.0])]
        for n, baseline in zip(plot.data, baselines, strict=True):
            assert_data_equal(plot.data[n].data.Baseline.to_numpy(), baseline)
