from __future__ import absolute_import, division, unicode_literals

import pytest
from datetime import datetime, date

from bokeh.models.widgets import FileInput as BkFileInput
from panel.widgets import (Checkbox, DatePicker, DatetimeInput, FileInput,
                           LiteralInput, TextInput, StaticText)


def test_checkbox(document, comm):

    checkbox = Checkbox(value=True, name='Checkbox')

    widget = checkbox.get_root(document, comm=comm)

    assert isinstance(widget, checkbox._widget_type)
    assert widget.labels == ['Checkbox']
    assert widget.active == [0]

    widget.active = []
    checkbox._comm_change({'active': []})
    assert checkbox.value == False

    checkbox.value = True
    assert widget.active == [0]


def test_date_picker(document, comm):
    date_picker = DatePicker(name='DatePicker', value=datetime(2018, 9, 2),
                             start=datetime(2018, 9, 1), end=datetime(2018, 9, 10))

    widget = date_picker.get_root(document, comm=comm)

    assert isinstance(widget, date_picker._widget_type)
    assert widget.title == 'DatePicker'
    assert widget.value == datetime(2018, 9, 2)
    assert widget.min_date == datetime(2018, 9, 1)
    assert widget.max_date == datetime(2018, 9, 10)

    widget.value = 'Mon Sep 03 2018'
    date_picker._comm_change({'value': 'Mon Sep 03 2018'})
    assert date_picker.value == datetime(2018, 9, 3)

    date_picker._comm_change({'value': date(2018, 9, 5)})
    assert date_picker.value == date(2018, 9, 5)

    date_picker._comm_change({'value': datetime(2018, 9, 6)})
    assert date_picker.value == datetime(2018, 9, 6)

    date_picker.value = datetime(2018, 9, 4)
    assert widget.value == date_picker.value


def test_file_input(document, comm):
    file_input = FileInput()

    widget = file_input.get_root(document, comm=comm)

    assert isinstance(widget, BkFileInput)

    file_input._comm_change({'mime_type': 'text/plain', 'value': 'U29tZSB0ZXh0Cg=='})
    assert file_input.value == b'Some text\n'
    assert file_input.mime_type == 'text/plain'


def test_literal_input(document, comm):

    literal = LiteralInput(value={}, type=dict, name='Literal')

    widget = literal.get_root(document, comm=comm)

    assert isinstance(widget, literal._widget_type)
    assert widget.title == 'Literal'
    assert widget.value == '{}'

    literal._comm_change({'value': "{'key': (0, 2)}"})
    assert literal.value == {'key': (0, 2)}
    assert widget.title == 'Literal'

    literal._comm_change({'value': "(0, 2)"})
    assert literal.value == {'key': (0, 2)}
    assert widget.title == 'Literal (wrong type)'

    literal._comm_change({'value': "invalid"})
    assert literal.value == {'key': (0, 2)}
    assert widget.title == 'Literal (invalid)'

    literal._comm_change({'value': "{'key': (0, 3)}"})
    assert literal.value == {'key': (0, 3)}
    assert widget.title == 'Literal'

    with pytest.raises(ValueError):
        literal.value = []


def test_static_text(document, comm):

    text = StaticText(value='ABC', name='Text:')

    widget = text.get_root(document, comm=comm)

    assert isinstance(widget, text._widget_type)
    assert widget.text == '<b>Text:</b>: ABC'

    text.value = 'CBA'
    assert widget.text == '<b>Text:</b>: CBA'


def test_text_input(document, comm):

    text = TextInput(value='ABC', name='Text:')

    widget = text.get_root(document, comm=comm)

    assert isinstance(widget, text._widget_type)
    assert widget.value == 'ABC'
    assert widget.title == 'Text:'

    text._comm_change({'value': 'CBA'})
    assert text.value == 'CBA'

    text.value = 'A'
    assert widget.value == 'A'

def test_datetime_input(document, comm):
    dt_input = DatetimeInput(value=datetime(2018, 1, 1),
                             start=datetime(2017, 12, 31),
                             end=datetime(2018, 1, 10),
                             name='Datetime')

    widget = dt_input.get_root(document, comm=comm)

    assert isinstance(widget, dt_input._widget_type)
    assert widget.title == 'Datetime'
    assert widget.value == '2018-01-01 00:00:00'

    dt_input._comm_change({'value': '2018-01-01 00:00:01'})
    assert dt_input.value == datetime(2018, 1, 1, 0, 0, 1)
    assert widget.title == 'Datetime'

    dt_input._comm_change({'value': '2018-01-01 00:00:01a'})
    assert dt_input.value == datetime(2018, 1, 1, 0, 0, 1)
    assert widget.title == 'Datetime (invalid)'

    dt_input._comm_change({'value': '2018-01-11 00:00:00'})
    assert dt_input.value == datetime(2018, 1, 1, 0, 0, 1)
    assert widget.title == 'Datetime (out of bounds)'

    dt_input._comm_change({'value': '2018-01-02 00:00:01'})
    assert dt_input.value == datetime(2018, 1, 2, 0, 0, 1)
    assert widget.title == 'Datetime'

    with pytest.raises(ValueError):
        dt_input.value = datetime(2017, 12, 30)
