# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals

from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.select import Select
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from urllib import unquote
import time, subprocess
import signal
import sys

host = "http://localhost"
pipe = None
port = "8000"
_driver = None
_verbose = None
logged_in = False
cur_route = False
input_wait = 0

def get_localhost():
	return "{host}:{port}".format(host=host, port=port)

def start(verbose=None, driver=None):
	global _driver, _verbose
	_verbose = verbose

	_driver = getattr(webdriver, driver or "PhantomJS")()
	_driver.set_window_size(1080,800)

	signal.signal(signal.SIGINT, signal_handler)

def signal_handler(signal, frame):
	close()
	sys.exit(0)

def start_test_server(verbose):
	global pipe
	pipe = subprocess.Popen(["bench", "serve", "--port", port], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	#time.sleep(5)
	while not pipe.stderr.readline():
		time.sleep(0.5)
	if verbose:
		print "Test server started"

def get(url):
	_driver.get(url)

def login(wait_for_id="#page-desktop"):
	global logged_in
	if logged_in:
		return
	get(get_localhost() + "/login")
	wait("#login_email")
	set_input("#login_email", "Administrator")
	set_input("#login_password", "admin", key=Keys.RETURN)
	wait(wait_for_id)
	logged_in = True


def go_to_module(module_name, item=None):
	global cur_route

	# desktop
	find(".navbar-home", True)[0].click()
	cur_route = None
	wait("#page-desktop")

	page = "Module/" + module_name
	m = find('#page-desktop [data-link="{0}"] .app-icon'.format(page))
	if not m:
		page = "List/" + module_name
		m = find('#page-desktop [data-link="{0}"] .app-icon'.format(page))
	if not m:
		raise Exception, "Module {0} not found".format(module_name)

	m[0].click()
	wait_for_page(page)

	if item:
		elem = find('[data-label="{0}"]'.format(item))[0]
		elem.click()
		page = elem.get_attribute("data-route")
		wait_for_page(page)

def new_doc(module, doctype):
	go_to_module(module, doctype)
	primary_action()
	wait_for_page("Form/" + doctype)

def add_child(fieldname):
	find('[data-fieldname="{0}"] .grid-add-row'.format(fieldname))[0].click()
	wait('[data-fieldname="{0}"] .form-grid'.format(fieldname))

def done_add_child(fieldname):
	selector = '[data-fieldname="{0}"] .grid-row-open .btn-success'.format(fieldname)
	scroll_to(selector)
	wait_till_clickable(selector).click()

def find(selector, everywhere=False):
	if cur_route and not everywhere:
		selector = cur_route + " " + selector
	return _driver.find_elements_by_css_selector(selector)

def set_field(fieldname, value, fieldtype="input"):
	_driver.switch_to.window(_driver.current_window_handle)
	selector = '{0}[data-fieldname="{1}"]'.format(fieldtype, fieldname)
	set_input(selector, value, key=Keys.TAB)
	wait_for_ajax()

def set_select(fieldname, value):
	select = Select(find('select[data-fieldname="{0}"]'.format(fieldname))[0])
	select.select_by_value(value)
	wait_for_ajax()

def primary_action():
	selector = ".page-actions .primary-action"
	scroll_to(selector)
	wait_till_clickable(selector).click()
	wait_for_ajax()

def wait_for_page(name):
	global cur_route
	cur_route = None
	route = '[data-page-route="{0}"]'.format(name)
	wait_for_ajax()
	elem = wait(route)
	wait_for_ajax()
	cur_route = route
	return elem

def wait_till_clickable(selector):
	if cur_route:
		selector = cur_route + " " + selector
	return get_wait().until(EC.element_to_be_clickable((By.CSS_SELECTOR, selector)))

def wait_till_visible(selector):
	if cur_route:
		selector = cur_route + " " + selector
	return get_wait().until(EC.visibility_of_element_located((By.CSS_SELECTOR, selector)))

def wait_for_ajax():
	wait('body[data-ajax-state="complete"]', True)

def wait_for_state(state):
	return wait(cur_route + '[data-state="{0}"]'.format(state), True)

def wait(selector, everywhere=False):
	if cur_route and not everywhere:
		selector = cur_route + " " + selector

	time.sleep(0.5)
	elem = get_wait().until(EC.presence_of_element_located((By.CSS_SELECTOR, selector)))
	return elem

def get_wait():
	return WebDriverWait(_driver, 20)

def set_input(selector, text, key=None):
	elem = find(selector)[0]
	elem.clear()
	elem.send_keys(text)
	if key:
		time.sleep(0.5)
		elem.send_keys(key)
	if input_wait:
		time.sleep(input_wait)

def scroll_to(selector):
	execute_script("frappe.ui.scroll('{0}')".format(selector))

def execute_script(js):
	_driver.execute_script(js)

def close():
	global _driver, pipe
	if _driver:
		_driver.quit()
	if pipe:
		pipe.kill()
	_driver = pipe = None
