from lettuce import world, step
from lettuce.django import django_url
from nose.tools import assert_true
from nose.tools import assert_equal
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import WebDriverException, StaleElementReferenceException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

from terrain.factories import UserFactory, RegistrationFactory, UserProfileFactory
from terrain.factories import CourseFactory, GroupFactory
from xmodule.modulestore.django import _MODULESTORES, modulestore
from xmodule.templates import update_templates
from auth.authz import get_user_by_email

from logging import getLogger
logger = getLogger(__name__)

###########  STEP HELPERS ##############
@step('I (?:visit|access|open) the Studio homepage$')
def i_visit_the_studio_homepage(step):
    # To make this go to port 8001, put
    # LETTUCE_SERVER_PORT = 8001
    # in your settings.py file.
    world.browser.visit(django_url('/'))
    signin_css = 'a.action-signin'
    assert world.browser.is_element_present_by_css(signin_css, 10)


@step('I am logged into Studio$')
def i_am_logged_into_studio(step):
    log_into_studio()


@step('I confirm the alert$')
def i_confirm_with_ok(step):
    world.browser.get_alert().accept()


@step(u'I press the "([^"]*)" delete icon$')
def i_press_the_category_delete_icon(step, category):
    if category == 'section':
        css = 'a.delete-button.delete-section-button span.delete-icon'
    elif category == 'subsection':
        css = 'a.delete-button.delete-subsection-button  span.delete-icon'
    else:
        assert False, 'Invalid category: %s' % category
    css_click(css)


@step('I have opened a new course in Studio$')
def i_have_opened_a_new_course(step):
    clear_courses()
    log_into_studio()
    create_a_course()


####### HELPER FUNCTIONS ##############
def create_studio_user(
        uname='robot',
        email='robot+studio@edx.org',
        password='test',
        is_staff=False):
    studio_user = UserFactory.build(
        username=uname,
        email=email,
        password=password,
        is_staff=is_staff)
    studio_user.set_password(password)
    studio_user.save()

    registration = RegistrationFactory(user=studio_user)
    registration.register(studio_user)
    registration.activate()

    user_profile = UserProfileFactory(user=studio_user)


def flush_xmodule_store():
    # Flush and initialize the module store
    # It needs the templates because it creates new records
    # by cloning from the template.
    # Note that if your test module gets in some weird state
    # (though it shouldn't), do this manually
    # from the bash shell to drop it:
    # $ mongo test_xmodule --eval "db.dropDatabase()"
    _MODULESTORES = {}
    modulestore().collection.drop()
    update_templates()


def assert_css_with_text(css, text):
    assert_true(world.browser.is_element_present_by_css(css, 5))
    assert_equal(world.browser.find_by_css(css).text, text)


def css_click(css):
    '''
    First try to use the regular click method, 
    but if clicking in the middle of an element
    doesn't work it might be that it thinks some other
    element is on top of it there so click in the upper left
    '''
    try:
        css_find(css).first.click()
    except WebDriverException, e:
        css_click_at(css)


def css_click_at(css, x=10, y=10):
    '''
    A method to click at x,y coordinates of the element
    rather than in the center of the element
    '''
    e = css_find(css).first
    e.action_chains.move_to_element_with_offset(e._element, x, y)
    e.action_chains.click()
    e.action_chains.perform()


def css_fill(css, value):
    world.browser.find_by_css(css).first.fill(value)


def css_find(css):
    def is_visible(driver):
        return EC.visibility_of_element_located((By.CSS_SELECTOR,css,))

    world.browser.is_element_present_by_css(css, 5)
    wait_for(is_visible)
    return world.browser.find_by_css(css)


def wait_for(func):
    WebDriverWait(world.browser.driver, 5).until(func)


def id_find(id):
    return world.browser.find_by_id(id)


def clear_courses():
    flush_xmodule_store()


def fill_in_course_info(
        name='Robot Super Course',
        org='MITx',
        num='101'):
    css_fill('.new-course-name', name)
    css_fill('.new-course-org', org)
    css_fill('.new-course-number', num)


def log_into_studio(
        uname='robot',
        email='robot+studio@edx.org',
        password='test',
        is_staff=False):
    create_studio_user(uname=uname, email=email, is_staff=is_staff)
    world.browser.cookies.delete()
    world.browser.visit(django_url('/'))
    signin_css = 'a.action-signin'
    world.browser.is_element_present_by_css(signin_css, 10)

    # click the signin button
    css_click(signin_css)

    login_form = world.browser.find_by_css('form#login_form')
    login_form.find_by_name('email').fill(email)
    login_form.find_by_name('password').fill(password)
    login_form.find_by_name('submit').click()

    assert_true(world.browser.is_element_present_by_css('.new-course-button', 5))


def create_a_course():
    c = CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course')

    # Add the user to the instructor group of the course
    # so they will have the permissions to see it in studio
    g = GroupFactory.create(name='instructor_MITx/999/Robot_Super_Course')
    u = get_user_by_email('robot+studio@edx.org')
    u.groups.add(g)
    u.save()
    world.browser.reload()

    course_link_css = 'span.class-name'
    css_click(course_link_css)
    course_title_css = 'span.course-title'
    assert_true(world.browser.is_element_present_by_css(course_title_css, 5))


def add_section(name='My Section'):
    link_css = 'a.new-courseware-section-button'
    css_click(link_css)
    name_css = 'input.new-section-name'
    save_css = 'input.new-section-name-save'
    css_fill(name_css, name)
    css_click(save_css)
    span_css = 'span.section-name-span'
    assert_true(world.browser.is_element_present_by_css(span_css, 5))


def add_subsection(name='Subsection One'):
    css = 'a.new-subsection-item'
    css_click(css)
    name_css = 'input.new-subsection-name-input'
    save_css = 'input.new-subsection-name-save'
    css_fill(name_css, name)
    css_click(save_css)
