# disable missing docstring
# pylint: disable=C0111

import os
from lettuce import world, step

from django.conf import settings

from xmodule.contentstore.content import StaticContent
from xmodule.contentstore.django import contentstore
from xmodule.exceptions import NotFoundError
from splinter.request_handler.request_handler import RequestHandler

TEST_ROOT = settings.COMMON_TEST_DATA_ROOT

# We should wait 300 ms for event handler invocation + 200ms for safety.
DELAY = 0.5

ERROR_MESSAGES = {
    'url_format': u'Incorrect url format.',
    'file_type': u'Link types should be unique.',
}

STATUSES = {
    'found': u'Timed Transcript Found',
    'not found': u'No Timed Transcript',
    'replace': u'Timed Transcript Conflict',
    'uploaded_successfully': u'Timed Transcript uploaded successfully',
    'use existing': u'Timed Transcript Not Updated',
}

SELECTORS = {
    'error_bar': '.transcripts-error-message',
    'url_inputs': '.videolist-settings-item input.input',
    'collapse_link': '.collapse-action.collapse-setting',
    'collapse_bar': '.videolist-extra-videos',
    'status_bar': '.transcripts-message-status',
}

# button type , button css selector, button message
TRANSCRIPTS_BUTTONS = {
    'import': ('.setting-import',  'Import from YouTube'),
    'download_to_edit': ('.setting-download', 'Download to Edit'),
    'disabled_download_to_edit': ('.setting-download.is-disabled', 'Download to Edit'),
    'upload_new_timed_transcripts': ('.setting-upload',  'Upload New Timed Transcript'),
    'replace': ('.setting-replace', 'Yes, Replace EdX Timed Transcript with YouTube Timed Transcript'),
    'choose': ('.setting-choose', 'Timed Transcript from {}'),
    'use_existing': ('.setting-use-existing', 'Use Existing Timed Transcript'),
}


@step('I clear fields$')
def clear_fields(_step):

    # Clear the input fields and trigger an 'input' event
    script = """
        $('{selector}')
            .prop('disabled', false)
            .removeClass('is-disabled')
            .val('')
            .trigger('input');
    """.format(selector=SELECTORS['url_inputs'])
    world.browser.execute_script(script)

    world.wait(DELAY)
    world.wait_for_ajax_complete()


@step('I clear field number (.+)$')
def clear_field(_step, index):
    index = int(index) - 1
    world.css_fill(SELECTORS['url_inputs'], '', index)

    # For some reason ChromeDriver doesn't trigger an 'input' event after filling
    # the field with an empty value. That's why we trigger it manually via jQuery.
    world.trigger_event(SELECTORS['url_inputs'], event='input', index=index)

    world.wait(DELAY)
    world.wait_for_ajax_complete()


@step('I expect (.+) inputs are disabled$')
def inputs_are_disabled(_step, indexes):
    index_list = [int(i.strip()) - 1 for i in indexes.split(',')]
    for index in index_list:
        el = world.css_find(SELECTORS['url_inputs'])[index]

        assert el['disabled']


@step('I expect inputs are enabled$')
def inputs_are_enabled(_step):
    for index in range(3):
        el = world.css_find(SELECTORS['url_inputs'])[index]

        assert not el['disabled']


@step('I do not see error message$')
def i_do_not_see_error_message(_step):
    assert not world.css_visible(SELECTORS['error_bar'])


@step('I see error message "([^"]*)"$')
def i_see_error_message(_step, error):
    assert world.css_has_text(SELECTORS['error_bar'], ERROR_MESSAGES[error])


@step('I do not see status message$')
def i_do_not_see_status_message(_step):
    assert not world.css_visible(SELECTORS['status_bar'])


@step('I see status message "([^"]*)"$')
def i_see_status_message(_step, status):
    assert not world.css_visible(SELECTORS['error_bar'])
    assert world.css_has_text(SELECTORS['status_bar'], STATUSES[status])

    DOWNLOAD_BUTTON = TRANSCRIPTS_BUTTONS["download_to_edit"][0]
    if world.is_css_present(DOWNLOAD_BUTTON, wait_time=1) \
    and not world.css_find(DOWNLOAD_BUTTON)[0].has_class('is-disabled'):
        assert _transcripts_are_downloaded()


@step('I (.*)see button "([^"]*)"$')
def i_see_button(_step, not_see, button_type):
    button = button_type.strip()

    if not_see.strip():
        assert world.is_css_not_present(TRANSCRIPTS_BUTTONS[button][0])
    else:
        assert world.css_has_text(TRANSCRIPTS_BUTTONS[button][0], TRANSCRIPTS_BUTTONS[button][1])


@step('I (.*)see (.*)button "([^"]*)" number (\d+)$')
def i_see_button_with_custom_text(_step, not_see, button_type, custom_text, index):
    button = button_type.strip()
    custom_text = custom_text.strip()
    index = int(index.strip()) - 1

    if not_see.strip():
        assert world.is_css_not_present(TRANSCRIPTS_BUTTONS[button][0])
    else:
        assert world.css_has_text(TRANSCRIPTS_BUTTONS[button][0], TRANSCRIPTS_BUTTONS[button][1].format(custom_text), index)


@step('I click transcript button "([^"]*)"$')
def click_button_transcripts_variant(_step, button_type):
    button = button_type.strip()
    world.css_click(TRANSCRIPTS_BUTTONS[button][0])
    world.wait_for_ajax_complete()


@step('I click transcript button "([^"]*)" number (\d+)$')
def click_button_index(_step, button_type, index):
    button = button_type.strip()
    index = int(index.strip()) - 1

    world.css_click(TRANSCRIPTS_BUTTONS[button][0], index)
    world.wait_for_ajax_complete()


@step('I remove "([^"]+)" transcripts id from store')
def remove_transcripts_from_store(_step, subs_id):
    """Remove from store, if transcripts content exists."""
    filename = 'subs_{0}.srt.sjson'.format(subs_id.strip())
    content_location = StaticContent.compute_location(
        world.scenario_dict['COURSE'].org,
        world.scenario_dict['COURSE'].number,
        filename
    )
    try:
        content = contentstore().find(content_location)
        contentstore().delete(content.get_id())
        print('Transcript file was removed from store.')
    except NotFoundError:
        print('Transcript file was NOT found and not removed.')


@step('I enter a "([^"]+)" source to field number (\d+)$')
def i_enter_a_source(_step, link, index):
    index = int(index) - 1

    if index is not 0 and not world.css_visible(SELECTORS['collapse_bar']):
        world.css_click(SELECTORS['collapse_link'])

        assert world.css_visible(SELECTORS['collapse_bar'])

    world.css_fill(SELECTORS['url_inputs'], link, index)
    world.wait(DELAY)
    world.wait_for_ajax_complete()


@step('I upload the transcripts file "([^"]*)"$')
def upload_file(_step, file_name):
    path = os.path.join(TEST_ROOT, 'uploads/', file_name.strip())
    world.browser.execute_script("$('form.file-chooser').show()")
    world.browser.attach_file('transcript-file', os.path.abspath(path))
    world.wait_for_ajax_complete()


@step('I see "([^"]*)" text in the captions')
def check_text_in_the_captions(_step, text):
    world.wait_for(lambda _: world.css_text('.subtitles'))
    actual_text = world.css_text('.subtitles')
    assert (text in actual_text)


@step('I see value "([^"]*)" in the field "([^"]*)"$')
def check_transcripts_field(_step, values, field_name):
    world.click_link_by_text('Advanced')
    field_id = '#' + world.browser.find_by_xpath('//label[text()="%s"]' % field_name.strip())[0]['for']
    values_list = [i.strip() == world.css_value(field_id) for i in values.split('|')]
    assert any(values_list)
    world.click_link_by_text('Basic')


@step('I save changes$')
def save_changes(_step):
    save_css = 'a.save-button'
    world.css_click(save_css)
    world.wait_for_ajax_complete()


@step('I open tab "([^"]*)"$')
def open_tab(_step, tab_name):
    world.click_link_by_text(tab_name.strip())
    world.wait_for_ajax_complete()


@step('I set value "([^"]*)" to the field "([^"]*)"$')
def set_value_transcripts_field(_step, value, field_name):
    XPATH = '//label[text()="{name}"]'.format(name=field_name)
    SELECTOR = '#' + world.browser.find_by_xpath(XPATH)[0]['for']
    element = world.css_find(SELECTOR).first
    if element['type'] == 'text':
        SCRIPT = '$("{selector}").val("{value}").change()'.format(
                selector=SELECTOR,
                value=value
            )
        world.browser.execute_script(SCRIPT)
        assert world.css_has_value(SELECTOR, value)
    else:
        assert False, 'Incorrect element type.';
    world.wait_for_ajax_complete()


@step('I revert the transcript field "([^"]*)"$')
def revert_transcripts_field(_step, field_name):
    world.revert_setting_entry(field_name)


def _transcripts_are_downloaded():
    world.wait_for_ajax_complete()
    request = RequestHandler()
    DOWNLOAD_BUTTON = world.css_find(TRANSCRIPTS_BUTTONS["download_to_edit"][0]).first
    url = DOWNLOAD_BUTTON['href']
    request.connect(url)

    return request.status_code.is_success()
