import dash_ag_grid as dag
from dash import Dash, html, dcc, Output, Input, no_update, ctx, State
import requests
from . import utils
import json
from dash.testing.wait import until
import time


def test_sb001_sizing_buttons(dash_duo):
    app = Dash(__name__)

    data = requests.get(
        r"https://www.ag-grid.com/example-assets/olympic-winners.json"
    ).json()

    columnDefs = [
        {"field": "athlete"},
        {"field": "age"},
        {"field": "country"},
        {"field": "year"},
        {"field": "date"},
        {"field": "sport"},
        {"field": "gold"},
        {"field": "silver"},
        {"field": "bronze"},
        {"field": "total"},
    ]

    app.layout = html.Div(
        [
            dcc.Markdown("This grid has single-select rows."),
            dag.AgGrid(
                id="grid",
                columnDefs=columnDefs,
                rowData=data[:100],
                columnSize="sizeToFit",
                defaultColDef={
                    "resizable": True,
                    "sortable": True,
                    "filter": True,
                    "floatingFilter": True,
                },
                dashGridOptions={"rowSelection": "multiple"},
                persistence=True,
                persistence_type="session",
            ),
            html.Button(id="autoSizeAllColumns", children="Auto Size All"),
            html.Button(
                id="autoSizeAllColumnsSkipHeaders", children="Auto Size All SkipHeaders"
            ),
            html.Div(id="columnState"),
        ],
        style={"margin": 20},
    )

    @app.callback(
        Output("grid", "columnSize", allow_duplicate=True),
        Output("grid", "columnSizeOptions", allow_duplicate=True),
        Input("autoSizeAllColumns", "n_clicks"),
        prevent_initial_call=True,
    )
    def setSelection(n):
        if n:
            return "autoSize", {"skipHeader": False}
        return no_update, no_update

    @app.callback(
        Output("grid", "columnSize", allow_duplicate=True),
        Output("grid", "columnSizeOptions", allow_duplicate=True),
        Input("autoSizeAllColumnsSkipHeaders", "n_clicks"),
        prevent_initial_call=True,
    )
    def setSelection(n):
        if n:
            return "autoSize", {"skipHeader": True}
        return no_update, no_update

    @app.callback(
        Output("columnState", "children"),
        Input("grid", "columnState"),
        State("columnState", "children"),
        State("grid", "columnSizeOptions"),
    )
    def selected(state, oldState, opts):
        if state:
            test = True
            if oldState and opts == {"skipHeader": True}:
                oldState = json.loads(oldState)
                for i in range(len(state)):
                    if i in [1, 6, 7, 8, 9]:
                        if state[i]["width"] > oldState[i]["width"]:
                            test = False
                            break
            assert test
            return json.dumps(state)
        return ""

    dash_duo.start_server(app)

    grid = utils.Grid(dash_duo, "grid")

    grid.wait_for_cell_text(0, 0, "Michael Phelps")

    oldValue = ""
    until(lambda: oldValue != dash_duo.find_element("#columnState").text, timeout=3)
    oldValue = dash_duo.find_element("#columnState").text
    for x in columnDefs:
        assert x["field"] in oldValue

    for x in ["autoSizeAllColumns", "autoSizeAllColumnsSkipHeaders"]:
        dash_duo.find_element(f"#{x}").click()
        until(
            lambda: oldValue
            != dash_duo.find_element("#columnState").get_attribute("innerText"),
            timeout=3,
        )
        oldValue = dash_duo.find_element("#columnState").text


def test_sb002_sizing_buttons(dash_duo):
    app = Dash(__name__)

    data = requests.get(
        r"https://www.ag-grid.com/example-assets/olympic-winners.json"
    ).json()

    columnDefs = [
        {"field": "athlete"},
        {"field": "age"},
        {"field": "country"},
        {"field": "year"},
        {"field": "date"},
        {"field": "sport"},
        {"field": "gold"},
        {"field": "silver"},
        {"field": "bronze"},
        {"field": "total"},
    ]

    app.layout = html.Div(
        [
            dcc.Markdown("This grid has single-select rows."),
            dag.AgGrid(
                id="grid",
                columnDefs=columnDefs,
                rowData=data[:100],
                columnSize="autoSize",
                defaultColDef={
                    "resizable": True,
                    "sortable": True,
                    "filter": True,
                    "floatingFilter": True,
                },
                dashGridOptions={"rowSelection": "multiple"},
                persistence=True,
                persistence_type="session",
            ),
            html.Button(id="sizeToFit", children="sizeToFit"),
            html.Button(id="responsiveSizeToFit", children="responsiveSizeToFit"),
            html.Div(id="columnState"),
        ],
        style={"margin": 20},
    )

    @app.callback(
        Output("grid", "columnSize", allow_duplicate=True),
        Input("sizeToFit", "n_clicks"),
        prevent_initial_call=True,
    )
    def setSelection(n):
        if n:
            return "sizeToFit"
        return no_update

    @app.callback(
        Output("grid", "columnSize", allow_duplicate=True),
        Input("responsiveSizeToFit", "n_clicks"),
        prevent_initial_call=True,
    )
    def setSelection(n):
        if n:
            return "responsiveSizeToFit"
        return no_update

    @app.callback(
        Output("columnState", "children"),
        Input("grid", "columnState"),
    )
    def selected(state):
        if state:
            return json.dumps(state)
        return ""

    dash_duo.start_server(app)

    grid = utils.Grid(dash_duo, "grid")

    grid.wait_for_cell_text(0, 0, "Michael Phelps")
    dash_duo.driver.set_window_size(1000, 1000)
    oldValue = ""
    until(lambda: oldValue != dash_duo.find_element("#columnState").text, timeout=3)
    oldValue = dash_duo.find_element("#columnState").text
    for x in columnDefs:
        assert x["field"] in oldValue

    for x in ["sizeToFit", "responsiveSizeToFit"]:
        dash_duo.find_element(f"#{x}").click()
        if x != "responsiveSizeToFit":
            until(
                lambda: oldValue
                != dash_duo.find_element("#columnState").get_attribute("innerText"),
                timeout=3,
            )
        oldValue = dash_duo.find_element("#columnState").text
        dash_duo.driver.set_window_size(500, 500)
        if x == "responsiveSizeToFit":
            until(
                lambda: oldValue
                != dash_duo.find_element("#columnState").get_attribute("innerText"),
                timeout=3,
            )
        else:
            assert oldValue == dash_duo.find_element("#columnState").get_attribute(
                "innerText"
            )

        oldValue = dash_duo.find_element("#columnState").text
        dash_duo.driver.set_window_size(1000, 1000)


def test_sb003_sizing_buttons(dash_duo):
    app = Dash(__name__)

    data = requests.get(
        r"https://www.ag-grid.com/example-assets/olympic-winners.json"
    ).json()

    columnDefs = [
        {"field": "athlete"},
        {"field": "age"},
        {"field": "country"},
        {"field": "year"},
        {"field": "date"},
        {"field": "sport"},
        {"field": "gold"},
        {"field": "silver"},
        {"field": "bronze"},
        {"field": "total"},
    ]

    app.layout = html.Div(
        [
            dcc.Markdown("This grid has single-select rows."),
            dag.AgGrid(
                id="grid",
                columnDefs=columnDefs,
                rowData=data[:100],
                columnSize="sizeToFit",
                defaultColDef={
                    "resizable": True,
                    "sortable": True,
                    "filter": True,
                    "floatingFilter": True,
                },
                dashGridOptions={"rowSelection": "multiple"},
                persistence=True,
                persistence_type="session",
            ),
            html.Button(id="autoSizeOneColumn", children="Auto Size One"),
            html.Button(
                id="autoSizeOneColumnSkipHeaders", children="Auto Size One SkipHeaders"
            ),
            html.Div(id="columnState"),
        ],
        style={"margin": 20},
    )

    @app.callback(
        Output("grid", "columnSize", allow_duplicate=True),
        Output("grid", "columnSizeOptions", allow_duplicate=True),
        Input("autoSizeOneColumn", "n_clicks"),
        prevent_initial_call=True,
    )
    def setSelection(n):
        if n:
            return "autoSize", {"keys": ["gold"]}
        return no_update, no_update

    @app.callback(
        Output("grid", "columnSize", allow_duplicate=True),
        Output("grid", "columnSizeOptions", allow_duplicate=True),
        Input("autoSizeOneColumnSkipHeaders", "n_clicks"),
        prevent_initial_call=True,
    )
    def setSelection(n):
        if n:
            return "autoSize", {"skipHeader": True, "keys": ["gold"]}
        return no_update, no_update

    @app.callback(
        Output("columnState", "children"),
        Input("grid", "columnState"),
        State("columnState", "children"),
        State("grid", "columnSizeOptions"),
    )
    def selected(state, oldState, opts):
        if state:
            test = True
            if oldState and opts == {"skipHeader": True, "keys": ["gold"]}:
                oldState = json.loads(oldState)
                for i in range(len(state)):
                    if i in [6]:
                        if state[i]["width"] > oldState[i]["width"]:
                            test = False
                            break
            assert test
            return json.dumps(state)
        return ""

    dash_duo.start_server(app)

    grid = utils.Grid(dash_duo, "grid")

    grid.wait_for_cell_text(0, 0, "Michael Phelps")

    oldValue = ""
    until(lambda: oldValue != dash_duo.find_element("#columnState").text, timeout=3)
    oldValue = dash_duo.find_element("#columnState").text
    for x in columnDefs:
        assert x["field"] in oldValue

    for x in ["autoSizeOneColumn", "autoSizeOneColumnSkipHeaders"]:
        dash_duo.find_element(f"#{x}").click()
        until(
            lambda: oldValue
            != dash_duo.find_element("#columnState").get_attribute("innerText"),
            timeout=3,
        )
        oldValue = dash_duo.find_element("#columnState").text


def test_sb004_sizing_buttons(dash_duo):
    app = Dash(__name__)

    data = requests.get(
        r"https://www.ag-grid.com/example-assets/olympic-winners.json"
    ).json()

    columnDefs = [
        {"field": "athlete"},
        {"field": "age"},
        {"field": "country"},
        {"field": "year"},
        {"field": "date"},
        {"field": "sport"},
        {"field": "gold"},
        {"field": "silver"},
        {"field": "bronze"},
        {"field": "total"},
    ]

    app.layout = html.Div(
        [
            dcc.Markdown("This grid has single-select rows."),
            dag.AgGrid(
                id="grid",
                columnDefs=columnDefs,
                rowData=data[:100],
                columnSize="autoSize",
                defaultColDef={
                    "resizable": True,
                    "sortable": True,
                    "filter": True,
                    "floatingFilter": True,
                },
                dashGridOptions={"rowSelection": "multiple"},
                persistence=True,
                persistence_type="session",
            ),
            html.Button(id="sizeToFit", children="sizeToFit"),
            html.Button(id="responsiveSizeToFit", children="responsiveSizeToFit"),
            html.Div(id="columnState"),
        ],
        style={"margin": 20},
    )

    @app.callback(
        Output("grid", "columnSize", allow_duplicate=True),
        Output("grid", "columnSizeOptions", allow_duplicate=True),
        Input("sizeToFit", "n_clicks"),
        prevent_initial_call=True,
    )
    def setSelection(n):
        if n:
            return "sizeToFit", {"defaultMaxWidth": 50}
        return no_update, no_update

    @app.callback(
        Output("grid", "columnSize", allow_duplicate=True),
        Output("grid", "columnSizeOptions", allow_duplicate=True),
        Input("responsiveSizeToFit", "n_clicks"),
        prevent_initial_call=True,
    )
    def setSelection(n):
        if n:
            return "responsiveSizeToFit", {"defaultMinWidth": 50}
        return no_update, no_update

    @app.callback(
        Output("columnState", "children"),
        Input("grid", "columnState"),
    )
    def selected(state):
        if state:
            return json.dumps(state)
        return ""

    dash_duo.start_server(app)

    grid = utils.Grid(dash_duo, "grid")

    grid.wait_for_cell_text(0, 0, "Michael Phelps")
    dash_duo.driver.set_window_size(1000, 1000)
    oldValue = ""
    until(lambda: oldValue != dash_duo.find_element("#columnState").text, timeout=3)
    oldValue = dash_duo.find_element("#columnState").text
    for x in columnDefs:
        assert x["field"] in oldValue

    for x in ["sizeToFit", "responsiveSizeToFit"]:
        dash_duo.find_element(f"#{x}").click()
        if x != "responsiveSizeToFit":
            until(
                lambda: oldValue
                != dash_duo.find_element("#columnState").get_attribute("innerText"),
                timeout=3,
            )
        oldValue = dash_duo.find_element("#columnState").text
        dash_duo.driver.set_window_size(400, 400)
        if x == "responsiveSizeToFit":
            until(
                lambda: oldValue
                != dash_duo.find_element("#columnState").get_attribute("innerText"),
                timeout=3,
            )
        else:
            assert oldValue == dash_duo.find_element("#columnState").get_attribute(
                "innerText"
            )
            dash_duo.find_element(f"#{x}").click()
            until(
                lambda: oldValue
                != dash_duo.find_element("#columnState").get_attribute("innerText"),
                timeout=3,
            )

        oldValue = dash_duo.find_element("#columnState").text
        dash_duo.driver.set_window_size(1000, 1000)
