from typing import Optional, Union, TYPE_CHECKING

from copy import deepcopy

from pandas import DataFrame

from shimoku.plt.EChart_definitions.default_echart_options import (
    get_common_echart_options,
    get_common_series_options,
)

if TYPE_CHECKING:
    from shimoku.plt.plt_layer import PlotLayer


async def top_bottom_area_charts(
    self: "PlotLayer",
    data: Union[str, DataFrame, list[dict]],
    order: Optional[int] = None,
    x: str = "x",
    top_names: Optional[list[str]] = None,
    bottom_names: Optional[list[str]] = None,
    rows_size: Optional[int] = None,
    cols_size: Optional[int] = None,
    padding: Optional[str] = None,
    title: Optional[str] = None,
    x_axis_name: Optional[str] = None,
    top_axis_name: Optional[str] = None,
    bottom_axis_name: Optional[str] = None,
    option_modifications: Optional[dict] = None,
    variant: Optional[str] = None,
):
    if top_names is None:
        top_names = ["up"]

    if bottom_names is None:
        bottom_names = ["down"]

    common_options = get_common_echart_options()
    series_options = get_common_series_options()

    common_options.update(
        {
            "xAxis": [
                {
                    "name": x_axis_name if x_axis_name else "",
                    "type": "category",
                    "boundaryGap": True,
                    "axisLine": {"onZero": False},
                    "data": "#set_data#",
                }
            ],
            "yAxis": [
                {"name": top_axis_name if top_axis_name else "", "type": "value"},
                {
                    "name": bottom_axis_name if bottom_axis_name else "",
                    "nameLocation": "start",
                    "alignTicks": True,
                    "type": "value",
                    "inverse": True,
                },
            ],
        }
    )
    series_options.update(
        {
            "type": "line",
            "areaStyle": {"opacity": 0.5},
            "lineStyle": {"width": 1},
            "emphasis": {"focus": "series"},
            "markArea": {
                "silent": True,
                "itemStyle": {"opacity": 0.3},
            },
        }
    )
    series = []
    for name in bottom_names:
        aux_series_options = deepcopy(series_options)
        aux_series_options["name"] = name
        series.append(aux_series_options)

    for name in top_names:
        aux_series_options = deepcopy(series_options)
        aux_series_options["name"] = name
        aux_series_options["yAxisIndex"] = 1
        series.append(aux_series_options)

    await self._create_trend_chart(
        data_mapping_to_tuples=await self._choose_data(order, data),
        order=order,
        axes=x,
        values=bottom_names + top_names,
        rows_size=rows_size,
        cols_size=cols_size,
        padding=padding,
        title=title,
        x_axis_names=x_axis_name,
        y_axis_names=[bottom_axis_name, top_axis_name],
        echart_options=common_options,
        series_options=series,
        option_modifications=option_modifications,
        variant=variant,
    )


async def top_bottom_line_charts(
    self: "PlotLayer",
    data: Union[str, DataFrame, list[dict]],
    order: int,
    x: str,
    top_names: Optional[list[str]] = None,
    bottom_names: Optional[list[str]] = None,
    rows_size: int = 4,
    cols_size: Optional[int] = None,
    padding: Optional[str] = None,
    title: Optional[str] = None,
    x_axis_name: Optional[str] = None,
    top_axis_name: Optional[str] = None,
    bottom_axis_name: Optional[str] = None,
    option_modifications: Optional[dict] = None,
):
    if top_names is None:
        top_names = ["up"]

    if bottom_names is None:
        bottom_names = ["down"]

    common_options = get_common_echart_options()
    series_options = get_common_series_options()

    common_options.update(
        {
            "grid": [
                {"left": 60, "right": 50, "height": "35%"},
                {"left": 60, "right": 50, "top": "55%", "height": "35%"},
            ],
            "xAxis": [
                {
                    "name": x_axis_name if x_axis_name else "",
                    "type": "category",
                    "boundaryGap": False,
                    "axisLine": {"onZero": True},
                    "data": "#set_data#",
                    "label": {"show": False},
                },
                {
                    "gridIndex": 1,
                    "type": "category",
                    "boundaryGap": False,
                    "axisLine": {"onZero": True},
                    "position": "top",
                    "data": "#set_data#",
                },
            ],
            "yAxis": [
                {
                    "name": top_axis_name if top_axis_name else "",
                    "type": "value",
                    "nameLocation": "middle",
                    "nameGap": 40,
                },
                {
                    "gridIndex": 1,
                    "name": bottom_axis_name if bottom_axis_name else "",
                    "alignTicks": True,
                    "type": "value",
                    "inverse": True,
                    "nameLocation": "middle",
                    "nameGap": 40,
                },
            ],
        }
    )
    series_options.update(
        {
            "type": "line",
            "lineStyle": {"width": 1},
            "emphasis": {"focus": "series"},
            "markArea": {
                "silent": True,
                "itemStyle": {"opacity": 0.3},
            },
        }
    )
    series = []
    for name in bottom_names:
        aux_series_options = deepcopy(series_options)
        aux_series_options["name"] = name
        series.append(aux_series_options)

    for name in top_names:
        aux_series_options = deepcopy(series_options)
        aux_series_options["name"] = name
        aux_series_options["yAxisIndex"] = 1
        aux_series_options["xAxisIndex"] = 1
        series.append(aux_series_options)

    await self._create_trend_chart(
        data_mapping_to_tuples=await self._choose_data(order, data),
        order=order,
        axes=[x, x],
        values=bottom_names + top_names,
        option_modifications=option_modifications,
        rows_size=rows_size,
        cols_size=cols_size,
        padding=padding,
        title=title,
        x_axis_names=x_axis_name,
        y_axis_names=[bottom_axis_name, top_axis_name],
        echart_options=common_options,
        series_options=series,
    )
