package org.pinae.sarabi.service;

import java.io.BufferedReader;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.pinae.sarabi.service.filter.ServiceFilter;
import org.pinae.sarabi.service.listener.ContextListener;
import org.pinae.sarabi.service.listener.RequestListener;
import org.pinae.sarabi.service.util.RequestUtils;

public class ServiceExecutor {

	public ServiceResponse execute(ServiceConfig srvCfg, HttpServletRequest request) throws ServiceException {
		
		List<ServiceFilter> filterList = srvCfg.getFilters();
		if (filterList != null) {
			for (ServiceFilter filter : filterList) {
				if (filter != null) {
					ServiceResponse response = filter.filter(request);
					if (response.getStatus() != Http.HTTP_OK) {
						return response;
					}
				}
			}
		}

		Class<?> srvCls = srvCfg.getClazz();
		try {
			Object srvObj = srvCls.newInstance();
			
			if (srvObj instanceof RequestListener) {
				((RequestListener)srvObj).setRequest(request);
			}
			
			if (srvObj instanceof ContextListener) {
				((ContextListener)srvObj).handleRequest(request);
			}
			
			Method srvMethod = srvCfg.getMethod();

			List<Object> argList = new ArrayList<Object>();

			Map<String, String> uriParams = RequestUtils.getUrlParameter(srvCfg.getServiceUrl(), request.getRequestURI());
			Map<String, Object> queryParams = RequestUtils.getParameter(request);
			Map<String, String> httpHeaders = RequestUtils.getHeader(request);

			List<Pair<String, Parameter>> srvParams = srvCfg.getParams();
			for (Pair<String, Parameter> srvParam : srvParams) {
				String key = srvParam.getKey();
				if (key.equals("@body")) {
					BufferedReader br = request.getReader();
					StringBuffer strBuffer = new StringBuffer();
					
					String str = null;
					while((str = br.readLine()) != null){
						strBuffer.append(str);
					}
					argList.add(strBuffer.toString());
				} else {
					Object value = null;
					if (key.startsWith("@header")) {
						key = StringUtils.substringAfter(key, "@header.").toUpperCase();
						value = httpHeaders.get(key);
					} else {
						if (uriParams.containsKey(key)) {
							value = uriParams.get(key);
						} else {
							value = queryParams.get(key);
						}
					}
					
					if (value != null) {
						argList.add(value);
					} else {
						argList.add(null);
					}
				}
			}

			Object args[] = null;
			if (argList.size() > 0) {
				args = new Object[argList.size()];
				for (int i = 0; i < argList.size(); i++) {
					args[i] = argList.get(i);
				}
			}

			Object result = srvMethod.invoke(srvObj, args);
			
			ServiceResponse response = null;
			if (result != null) {
				if (result instanceof ServiceResponse) {
					response = (ServiceResponse)result;
				} else {
					response = new ServiceResponse(srvCfg.getContentType(), srvCfg.getCharset());
					response.setStatus(Http.HTTP_OK);
					if (result != null) {
						response.setContent(result);
					}
				}
			}
			
			if (srvObj instanceof ContextListener) {
				((ContextListener)srvObj).handleResponse(response);
			}
			
			return response;
			
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}
	


}

@@ -1834,19 +1834,23 @@
 if (
-key
+%22@body%22
 .equals(
 %22@bo
@@ -1845,23 +1845,19 @@
 .equals(
-%22@body%22
+key
 )) %7B%0A%09%09%09
@@ -2094,24 +2094,259 @@
 oString());%0A
+%09%09%09%09%7D else if (%22@url%22.equals(key)) %7B%0A%09%09%09%09%09argList.add(uriParams);%0A%09%09%09%09%7D else if (%22@query%22.equals(key) %7C%7C %22@parameter%22.equals(key)) %7B%0A%09%09%09%09%09argList.add(queryParams);%0A%09%09%09%09%7D else if (%22@header%22.equals(key)) %7B%0A%09%09%09%09%09argList.add(httpHeaders);%0A
 %09%09%09%09%7D else %7B
@@ -2975,115 +2975,465 @@
 %09%09%7D%0A
-%0A%09%09%09Object result = srvMethod.invoke(srvObj, args);%0A%09%09%09%0A%09%09%09ServiceResponse response = null;%0A%09%09%09if (result !
+%09%09%09%0A%09%09%09ServiceResponse response = null;%0A%09%09%09%0A%09%09%09Object result = null;%0A%09%09%09try %7B%0A%09%09%09%09result = srvMethod.invoke(srvObj, args);%0A%09%09%09%7D catch (IllegalArgumentException e1) %7B%0A%09%09%09%09response = new ServiceResponse(Http.HTTP_BAD_REQUEST, %22Illegal request argument:%22 + e1.getMessage());%0A%09%09%09%7D catch (IllegalAccessException e2) %7B%0A%09%09%09%09response = new ServiceResponse(Http.HTTP_INTERNAL_SERVER_ERROR, %22Illegal access method: %22 + srvMethod.getName());%0A%09%09%09%7D%0A%09%09%09%0A%09%09%09if (response =
 = nu
@@ -3479,24 +3479,52 @@
 Response) %7B%0A
+%09%09%09%09%09if (result != null) %7B%0A%09
 %09%09%09%09%09respons
@@ -3552,16 +3552,23 @@
 result;%0A
+%09%09%09%09%09%7D%0A
 %09%09%09%09%7D el

Add more field tag to ServiceExecutor