package greencode.jscript.dom;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.Map;
import greencode.exception.GreencodeError;
import greencode.http.enumeration.RequestMethod;
import greencode.jscript.DOM;
import greencode.jscript.DOMHandle;
import greencode.jscript.dom.annotation.QuerySelector;
import greencode.jscript.dom.elements.custom.ContainerElement;
import greencode.jscript.dom.elements.custom.implementation.ContainerElementImplementation;
import greencode.jscript.dom.form.annotation.ElementValue;
import greencode.jscript.dom.form.annotation.Event;
import greencode.jscript.dom.form.annotation.Name;
import greencode.jscript.dom.form.annotation.RegisterEvent;
import greencode.jscript.dom.form.annotation.Visible;
import greencode.kernel.GreenContext;
import greencode.util.ClassUtils;
import greencode.util.GenericReflection;
import greencode.util.GenericReflection.Condition;
import greencode.util.LogMessage;
public abstract class Form extends Element implements ContainerElementImplementation {
final Field[] elementFields = $Container.processFields(getClass());
Map<Integer, ContainerElement<?>> containers;
private static final Condition<Field> fieldsWithRegisterEvent = new Condition<Field>() {
public boolean init(Field arg0) {
return arg0.isAnnotationPresent(RegisterEvent.class) && ClassUtils.isParent(arg0.getType(), EventTarget.class);
}
};
private static final Condition<Field> fieldsWithFindElement = new Condition<Field>() {
public boolean init(Field arg0) {
return ClassUtils.isParent(arg0.getType(), Element.class) && (arg0.isAnnotationPresent(QuerySelector.class) || arg0.isAnnotationPresent(ElementValue.class));
}
};
protected Form() {
this(GreenContext.getInstance().currentWindow());
}
public Form(Window window) {
super(window, "form");
String name = getClass().getAnnotation(Name.class).value();
Visible visibleAnnotation = getClass().getAnnotation(Visible.class);
if(visibleAnnotation == null)
DOMHandle.registerReturnByCommand(this, window.principalElement(), "querySelector", "form[name=\"" + name + "\"]");
else
DOMHandle.registerReturnByCommand(this, window.principalElement(), "querySelector", "form[name=\"" + name + "\"]", "return (this.offsetHeight " + (visibleAnnotation.value() ? "!" : "=") + "== 0);");
}
void processAnnotation() {
Field[] fields = GenericReflection.getDeclaredFieldsByConditionId(getClass(), "form:fieldsWithFindElement");
if(fields == null)
fields = GenericReflection.getDeclaredFieldsByCondition(getClass(), "form:fieldsWithFindElement", fieldsWithFindElement, true);
for(Field f: fields) {
if(GenericReflection.NoThrow.getValue(f, this) != null)
continue;
QuerySelector a = f.getAnnotation(QuerySelector.class);
Object v = null;
Class<? extends Element> type = (Class<? extends Element>) f.getType();
if(a != null) {
Element context;
searchContext: {
if(!a.context().isEmpty()) {
for(Field f2: fields) {
if(f2.getName().equals(a.context())) {
context = (Element) GenericReflection.NoThrow.getValue(f2, this);
break searchContext;
}
}
throw new GreencodeError(LogMessage.getMessage("green-0041", a.context(), f.getName(), getClass().getSimpleName()));
}else
context = this;
}
if(type.isArray()) {
v = ElementHandle.cast(context.querySelectorAll(a.selector()), (Class<? extends Element>) type.getComponentType());
} else {
v = context.querySelector(a.selector(), type);
}
} else {
if(!type.isArray()) {
ElementValue aev = f.getAnnotation(ElementValue.class);
String name = aev.name().isEmpty() ? f.getName() : aev.name();
String selector = "[name='" + name + "']";
Class<?> typeValue = null;
if(greencode.jscript.dom.elements.$Element.isElementWithValue(type)) {
typeValue = f.getGenericType() instanceof ParameterizedType ? (Class<?>)((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0] : String.class;
}
v = this.querySelector(selector, type, typeValue);
DOMHandle.setVariableValue((DOM)v, "name", name);
}
}
GenericReflection.NoThrow.setValue(f, v, this);
}
fields = GenericReflection.getDeclaredFieldsByConditionId(getClass(), "form:elementsWithRegisterEvent");
if(fields == null)
fields = GenericReflection.getDeclaredFieldsByCondition(getClass(), "form:elementsWithRegisterEvent", fieldsWithRegisterEvent);
for(Field f: fields) {
Event[] events = f.getAnnotation(RegisterEvent.class).value();
EventTarget et = (EventTarget) GenericReflection.NoThrow.getValue(f, this);
if(et == null)
throw new RuntimeException(LogMessage.getMessage("green-0036", f.getName(), getClass().getSimpleName()));
for(Event e: events) {
FunctionHandle fh = new FunctionHandle(e.windowAction(), e.method());
fh.setRequestMethod(e.requestMethod());
for(String n: e.name())
et.addEventListener(n, fh);
}
}
}
public void acceptCharset(String acceptCharset) {
DOMHandle.setProperty(this, "acceptCharset", acceptCharset);
}
public String acceptCharset() {
return DOMHandle.getVariableValueByProperty(this, "acceptCharset", String.class, "acceptCharset");
}
public void action(String action) {
DOMHandle.setProperty(this, "action", action);
}
public String action() {
return DOMHandle.getVariableValueByProperty(this, "action", String.class, "action");
}
public void enctype(String enctype) {
DOMHandle.setProperty(this, "enctype", enctype);
}
public String enctype() {
return DOMHandle.getVariableValueByProperty(this, "enctype", String.class, "enctype");
}
public Integer length() {
return DOMHandle.getVariableValueByProperty(this, "length", Integer.class, "length");
}
public void method(RequestMethod method) {
DOMHandle.setProperty(this, "method", method);
}
public RequestMethod method() {
return RequestMethod.valueOf(DOMHandle.getVariableValueByProperty(this, "method", String.class, "method").toUpperCase());
}
public void name(String name) {
DOMHandle.setProperty(this, "name", name);
}
public String name() {
return DOMHandle.getVariableValueByProperty(this, "name", String.class, "name");
}
public void target(String target) {
DOMHandle.setProperty(this, "target", target);
}
public String target() {
return DOMHandle.getVariableValueByProperty(this, "target", String.class, "target");
}
public void reset() {
Field[] fields = greencode.jscript.dom.$Container.getElementFields(this);
try {
for(Field f: fields) {
Class<?> fieldType = f.getType();
if(greencode.jscript.dom.elements.$Element.isElementWithValue(fieldType))
DOMHandle.setVariableValue((Element) f.get(this), "value", null);
else
f.set(this, ClassUtils.getDefaultValue(fieldType));
}
} catch(Exception e) {
e.printStackTrace();
}
DOMHandle.execCommand(this, "resetForm");
}
public void submit() {
DOMHandle.execCommand(this, "submit");
}
public void fill() {
greencode.jscript.dom.$Container.fill(this, elementFields);
}
}