/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.suren.autotest.web.framework.selenium.action;

import com.surenpi.autotest.webui.ui.AbstractElement;
import org.eclipse.jetty.util.StringUtil;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.suren.autotest.web.framework.annotation.AutoData;
import org.suren.autotest.web.framework.selenium.SeleniumEngine;
import org.suren.autotest.web.framework.selenium.strategy.SearchStrategyUtils;

import com.surenpi.autotest.utils.StringUtils;
import com.surenpi.autotest.webui.action.AdvanceValueEditor;
import com.surenpi.autotest.webui.action.ValueEditor;
import com.surenpi.autotest.webui.ui.Element;

/**
 * 给文本框中填入值
 * @author <a href="http://surenpi.com">suren</a>
 */
@Component
public class SeleniumValueEditor implements ValueEditor, AdvanceValueEditor
{
	private static final Logger logger = LoggerFactory.getLogger(SeleniumValueEditor.class);

	@Autowired
	private SeleniumEngine			engine;
	@Autowired
	private SearchStrategyUtils		searchStrategyUtils;

	@Override
	public Object getValue(Element ele)
	{
		return searchStrategyUtils.findStrategy(WebElement.class, ele).search(ele).getText();
	}

	/**
	 * 实现逻辑：点击文本框、清空文本框、填入值 
	  */
	@Override
	public void setValue(Element ele, Object value)
	{
		fillValue(ele, value, false);
	}

	@Override
	public void appendValue(Element ele, Object value)
	{
		fillValue(ele, value, true);
	}

	@Override
	public void fillNotBlankValue(Element ele, Object value)
	{
		if(value == null || StringUtils.isBlank(value.toString()))
		{
			throw new RuntimeException("Can not allow null or empty value!");
		}
		
		fillValue(ele, value, true);
	}
	
	/**
	 * 填入值，如果目标元素有readonly，则不做任何操作
	 * @param ele 目标元素
	 * @param value 要填入的值，null会当作空字符串
	 * @param append 是否追加
	 */
	private void fillValue(Element ele, Object value, boolean append)
	{
		if(value == null)
		{
			value = "";
		}

		WebElement webEle = searchStrategyUtils.findStrategy(WebElement.class, ele).search(ele);
		if(webEle != null)
		{
			String readonlyAttr = webEle.getAttribute("readonly");
			if(StringUtil.isNotBlank(readonlyAttr))
			{
				logger.warn("{} is readonly, will do not call method setValue.", webEle.toString());
				return;
			}
			
			String valueStr = value.toString();
			try
			{
				fill(webEle, valueStr, append);
			}
			catch(WebDriverException e)
			{
				if(e.getMessage().contains("is not clickable at point"))
				{
					((JavascriptExecutor) engine.getDriver()).executeScript("arguments[0].scrollIntoView();", webEle);

					fill(webEle, valueStr, append);
				}
				else
				{
					e.printStackTrace();
				}
			}

			Object extraData = null;
			if (ele instanceof AbstractElement) {
				extraData = ((AbstractElement) ele).getData("data");
			}
			if (extraData != null) {
				logger.info(String.format("[%s] value filled", extraData));
			} else {
				logger.info(String.format("[%s] value filled", ele));
			}
		}
		else
		{
			logger.error(String.format("can not found element [%s].", ele));
		}
	}
	
	/**
	 * 填入值
	 * @param webEle
	 * @param value
	 * @param append
	 */
	private void fill(WebElement webEle, String value, boolean append)
	{
		webEle.click();
		if(!append)
		{
			webEle.clear();
		}
		webEle.sendKeys(value);
	}

	@Override
	public void submit(Element ele)
	{
		WebElement webEle = searchStrategyUtils.findStrategy(WebElement.class, ele).search(ele);
		webEle.submit();
	}

	@Override
	public boolean isEnabled(Element element)
	{
		return searchStrategyUtils.findStrategy(WebElement.class, element).search(element).isEnabled();
	}

	@Override
	public boolean isHidden(Element element)
	{
		return !searchStrategyUtils.findStrategy(WebElement.class, element).search(element).isDisplayed();
	}

}

@@ -918,32 +918,207 @@
 um.WebElement;%0D%0A
+import org.openqa.selenium.interactions.Actions;%0D%0Aimport org.openqa.selenium.NoSuchElementException;%0D%0Aimport org.openqa.selenium.WebDriver;%0D%0Aimport org.openqa.selenium.Keys;%0D%0A
 import org.slf4j
@@ -1278,70 +1278,8 @@
 t;%0D%0A
-import org.suren.autotest.web.framework.annotation.AutoData;%0D%0A
 impo
@@ -4470,16 +4470,28 @@
 (ele);%0D%0A
+%0D%0A%09%09try %7B%0D%0A%09
 %09%09webEle
@@ -4498,24 +4498,239 @@
 .submit();%0D%0A
+%09%09%7D catch (NoSuchElementException e) %7B%0D%0A%09%09%09logger.info(%22perhaps this element is not in a form%22, e);%0D%0A%0D%0A%09%09%09WebDriver driver = engine.getDriver();%0D%0A%09%09%09new Actions(driver).sendKeys(webEle, Keys.ENTER).perform();%0D%0A%09%09%7D%0D%0A
 %09%7D%0D%0A%0D%0A%09@Over

Improve the enter action of element (#73)