import pytest
import dash_html_components as html
import dash_core_components as dcc

from dash import Dash, callback_context

from dash.dependencies import Input, Output

from dash.exceptions import PreventUpdate, MissingCallbackContextException


def test_cbcx001_modified_response(dash_duo):
    app = Dash(__name__)
    app.layout = html.Div(
        [dcc.Input(id="input", value="ab"), html.Div(id="output")]
    )

    @app.callback(Output("output", "children"), [Input("input", "value")])
    def update_output(value):
        callback_context.response.set_cookie(
            "dash cookie", value + " - cookie"
        )
        return value + " - output"

    dash_duo.start_server(app)
    dash_duo.wait_for_text_to_equal("#output", "ab - output")
    input1 = dash_duo.find_element("#input")

    input1.send_keys("cd")

    dash_duo.wait_for_text_to_equal("#output", "abcd - output")
    cookie = dash_duo.driver.get_cookie("dash cookie")
    # cookie gets json encoded
    assert cookie["value"] == '"abcd - cookie"'

    assert not dash_duo.get_logs()


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

    btns = ["btn-{}".format(x) for x in range(1, 6)]

    app.layout = html.Div(
        [
            html.Div([html.Button(btn, id=btn) for btn in btns]),
            html.Div(id="output"),
        ]
    )

    @app.callback(
        Output("output", "children"), [Input(x, "n_clicks") for x in btns]
    )
    def on_click(*args):
        if not callback_context.triggered:
            raise PreventUpdate
        trigger = callback_context.triggered[0]
        return "Just clicked {} for the {} time!".format(
            trigger["prop_id"].split(".")[0], trigger["value"]
        )

    dash_duo.start_server(app)

    for i in range(1, 5):
        for btn in btns:
            dash_duo.find_element("#" + btn).click()
            dash_duo.wait_for_text_to_equal(
                "#output", "Just clicked {} for the {} time!".format(btn, i)
            )


def test_cbcx003_no_callback_context():
    for attr in ["inputs", "states", "triggered", "response"]:
        with pytest.raises(MissingCallbackContextException):
            getattr(callback_context, attr)


def test_cbcx004_triggered_backward_compat(dash_duo):
    app = Dash(__name__)
    app.layout = html.Div([
        html.Button("click!", id="btn"),
        html.Div(id="out")
    ])

    @app.callback(Output("out", "children"), [Input("btn", "n_clicks")])
    def report_triggered(n):
        triggered = callback_context.triggered
        bool_val = "truthy" if triggered else "falsy"
        split_propid = repr(triggered[0]["prop_id"].split("."))
        full_val = repr(triggered)
        return "triggered is {}, has prop/id {}, and full value {}".format(
            bool_val, split_propid, full_val
        )

    dash_duo.start_server(app)

    dash_duo.wait_for_text_to_equal(
        "#out",
        "triggered is falsy, has prop/id ['', ''], and full value "
        "[{'prop_id': '.', 'value': None}]"
    )

    dash_duo.find_element("#btn").click()
    dash_duo.wait_for_text_to_equal(
        "#out",
        "triggered is truthy, has prop/id ['btn', 'n_clicks'], and full value "
        "[{'prop_id': 'btn.n_clicks', 'value': 1}]"
    )

@@ -1,12 +1,24 @@
+import json%0A
 import pytes
@@ -19,16 +19,17 @@
  pytest%0A
+%0A
 import d
@@ -2620,20 +2620,26 @@
 ropid = 
-repr
+json.dumps
 (trigger
@@ -2690,12 +2690,18 @@
 l = 
-repr
+json.dumps
 (tri
@@ -2925,33 +2925,33 @@
 %22#out%22,%0A        
-%22
+'
 triggered is fal
@@ -2971,14 +2971,14 @@
 id %5B
-'', ''
+%22%22, %22%22
 %5D, a
@@ -2983,33 +2983,33 @@
  and full value 
-%22
+'
 %0A        %22%5B%7B'pro
@@ -3005,43 +3005,43 @@
     
-%22%5B%7B'
+'%5B%7B%22
 prop_id
-': '.', '
+%22: %22.%22, %22
 value
-': None%7D%5D%22
+%22: null%7D%5D'
 %0A   
@@ -3147,17 +3147,17 @@
         
-%22
+'
 triggere
@@ -3186,24 +3186,24 @@
 id %5B
-'btn', '
+%22btn%22, %22
 n_clicks
 '%5D, 
@@ -3198,17 +3198,17 @@
 n_clicks
-'
+%22
 %5D, and f
@@ -3217,17 +3217,17 @@
 l value 
-%22
+'
 %0A       
@@ -3231,23 +3231,23 @@
     
-%22%5B%7B'
+'%5B%7B%22
 prop_id
-': '
+%22: %22
 btn.
@@ -3258,24 +3258,24 @@
 icks
-', '
+%22, %22
 value
-'
+%22
 : 1%7D%5D
-%22
+'
 %0A   

fix callback_context test for py2