package jp.sourceforge.cfneo.at4ie.api.impl.ie;

import java.util.HashMap;
import java.util.Map;

import jp.sourceforge.cfneo.at4ie.api.AT4IERuntimeException;
import jp.sourceforge.cfneo.at4ie.api.TargetBrowser;

import org.apache.log4j.Logger;

import watij.dialogs.AlertDialog;
import watij.elements.Button;
import watij.elements.Buttons;
import watij.elements.HtmlElement;
import watij.elements.Option;
import watij.elements.Options;
import watij.elements.SelectList;
import watij.elements.TextField;
import watij.finders.Symbol;
import watij.finders.SymbolFactory;
import watij.runtime.ie.IE;
import watij.time.TimeException;

/**
 * watijのIEのWrapperクラス。
 * @author imaitakafumi
 *
 */
public class AT4IEInternetExplorer extends IE implements TargetBrowser {

	Logger logger = Logger.getLogger(AT4IEInternetExplorer.class);

	private boolean opened;

	/**
	 * コンストラクタ。
	 */
	public AT4IEInternetExplorer() {
		this.opened = false;
	}

	@Override
	public void open(String url) {
		try {
			if (this.opened) {
				super.goTo(url);
			} else {
				super.start(url);
			}
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickButton() {
		try {
			new AT4IEButton(this.button(0), this).click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickButtonById(String id) {
		logger.debug("AT4IEInternetExplorer#clickButtonById id=" + id);
		try {
			this.getButton(SymbolFactory.id, id).click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickButtonByName(String name) {
		try {
			this.getButton(SymbolFactory.name, name).click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickSubmit() {
		try {
			Buttons buttons = super.buttons();
			AT4IEButton button = null;
			for (Button b: buttons) {
				if ("submit".equals(b.type())) {
					button = new AT4IEButton(b, this);
					break;
				}
			}
			button.click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickSubmitById(String id) {
		try {
			Buttons buttons = super.buttons();
			AT4IEButton button = null;
			for (Button b: buttons) {
				if ("submit".equals(b.type()) && b.id().equals(id)) {
					button = new AT4IEButton(b, this);
					break;
				}
			}
			button.click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickSubmitByName(String name) {
		try {
			Buttons buttons = super.buttons();
			AT4IEButton button = null;
			for (Button b: buttons) {
				if ("submit".equals(b.type()) && b.name().equals(name)) {
					button = new AT4IEButton(b, this);
					break;
				}
			}
			button.click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void closeWindow() {
		try {
			super.close();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getScreenTitle() {
		try {
			return super.title();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void openWindow() {
		try {
			super.start("about:blank");
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void pushBrowserBack() {
		try {
			super.back();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void pushBrowserNext() {
		try {
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void saveScreenShot(String filepath) {
		try {
			this.windowCapture(filepath);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void typeById(String id, String value) {
		try {
			super.textField(SymbolFactory.id, id).set(value);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void typeByName(String name, String value) {
		try {
			super.textField(SymbolFactory.name, name).set(value);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getCurrentUrl() {
		try {
			return super.url();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getHiddenValueById(String id) {
		try {
			return super.hidden(SymbolFactory.id, id).value();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getHiddenValueByName(String name) {
		try {
			return super.hidden(SymbolFactory.name, name).value();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getTextValueById(String id) {
		try {
			return super.textField(SymbolFactory.id, id).value();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getTextValueByName(String name) {
		try {
			return super.textField(SymbolFactory.name, name).value();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickAlertDialogOk() {
		try {
			AlertDialog ad = this.alertDialog();
			if (ad.exists()) {
				ad.ok();
			}
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public AlertDialog alertDialog() {
		try {
			return super.alertDialog();
		} catch (Exception e) {
			if (e instanceof TimeException &&
					e.getMessage().equals("Timeout exceeded.  Reason= Could not find Dialog with title = Microsoft Internet Explorer")) {
				logger.error("watij.ie AlertDialog error!");
			} else {
				throw new AT4IERuntimeException(e);
			}
		}
		return new AT4IEAlertDialog();
	}
	@Override
	public String getAlertDialogText() {
		try {
			return this.alertDialog().text();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public boolean isOpened() {
		return this.opened;
	}
	@Override
	public Map<String, String> getSelectListById(String id) {
		SelectList selectList = this.getSelectComponentById(id);
		return this.createSelectListMap(selectList);
	}
	@Override
	public Map<String, String> getSelectListByName(String name) {
		SelectList selectList = this.getSelectComponentByName(name);
		return this.createSelectListMap(selectList);
	}
	@Override
	public void selectById(String id, String selectValue) {
		try {
			SelectList selectList = this.getSelectComponentById(id);
			selectList.selectValue(selectValue);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void selectByName(String name, String selectValue) {
		try {
			SelectList selectList = this.getSelectComponentByName(name);
			selectList.selectValue(selectValue);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getSelectedValueById(String id) {
		try {
			SelectList selectList = this.getSelectComponentById(id);
			return selectList.value();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getSelectedValueByName(String name) {
		try {
			SelectList selectList = this.getSelectComponentByName(name);
			return selectList.value();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void setValueById(String id, String value) {
		try {
			HtmlElement elem = super.htmlElement(SymbolFactory.id, id);
			this.setElementValue(elem, value);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void setValueByName(String name, String value) {
		try {
			HtmlElement elem = super.htmlElement(SymbolFactory.name, name);
			this.setElementValue(elem, value);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getValueById(String id) {
		try {
			return super.htmlElement(SymbolFactory.id, id).value();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getValueByName(String name) {
		try {
			return super.htmlElement(SymbolFactory.name, name).value();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getTextById(String id) {
		try {
			return super.htmlElement(SymbolFactory.id, id).text();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public String getTextByName(String name) {
		try {
			return super.htmlElement(SymbolFactory.name, name).text();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickLinkById(String id) {
		try {
			super.link(SymbolFactory.id, id).click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickLinkByName(String name) {
		try {
			super.link(SymbolFactory.name, name).click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	@Override
	public void clickLinkByUrl(String url) {
		try {
			super.link(SymbolFactory.href, url).click();
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}


	/**
	 * 指定したHTMLエレメントに値をセットする。
	 * @param element
	 * @param value
	 */
	protected void setElementValue(HtmlElement element, String value) {
		try {
			if ("text".equals(element.type()) == false
					|| "hidden".equals(element.type()) == false) {
				throw new AT4IERuntimeException(
						"Element type is unmatch. element.type=[" + element.type() + "]");
			}
			((TextField) element).set(value);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	/**
	 * 指定したid属性と合致するselectコンポーネントを取得する。
	 * @param id
	 * @return
	 */
	protected SelectList getSelectComponentById(String id) {
		try {
			return super.selectList(SymbolFactory.id, id);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	/**
	 * 指定したname属性と合致するselectコンポーネントを取得する。
	 * @param name
	 * @return
	 */
	protected SelectList getSelectComponentByName(String name) {
		try {
			return super.selectList(SymbolFactory.name, name);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	/**
	 * 指定されたselectからoptionの一覧(map)を作成する。
	 * @param selectList
	 * @return
	 */
	protected Map<String, String> createSelectListMap(SelectList selectList) {
		try {
			Options options = selectList.options();
			Map<String, String> map = new HashMap<String, String>();
			for (Option o: options) {
				map.put(o.text(), o.value());
			}
			return map;
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}
	/**
	 * 指定されたsymbol、keyを元にボタンを取得する。
	 * @param symbol
	 * @param key
	 * @return
	 */
	protected AT4IEButton getButton(Symbol symbol, String key) {
		try {
			return new AT4IEButton(super.button(symbol, key), this);
		} catch (Exception e) {
			throw new AT4IERuntimeException(e);
		}
	}

}
