package com.jasamedika.medifirst2000.filter;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.jasamedika.medifirst2000.constants.Constants;

/**
 * CORSFilter class
 * 
 * @author Roberto
 */
@Component
public class CORSFilter implements Filter {
	
	// Start Syamsu
	private static class RequestWrapper extends HttpServletRequestWrapper {
		final String body;
		
		public RequestWrapper(ServletRequest req) throws IOException {
			super((HttpServletRequest) req);
			
			HttpServletRequest request = (HttpServletRequest) req;
			
			StringBuilder stringBuilder = new StringBuilder();
			   BufferedReader reader = null;
			   try {
			     InputStream inputStream = request.getInputStream();
			     if (inputStream != null) {
			       reader = new BufferedReader(new InputStreamReader(inputStream));
			       String hasil;
			       while ( (hasil = reader.readLine()) != null) {
			         stringBuilder.append(hasil);
			       }
			     } else {
			       stringBuilder.append("");
			     }
			   } catch (IOException ex) {
			       throw ex;
			   } finally {
			     if (reader != null) {
			       try {
			         reader.close();
			       } catch (IOException ex) {
			         throw ex;
			       }
			     }
			   }
			   body = stringBuilder.toString();
			   
			   String idRuanganTujuan = request.getHeader(Constants.HttpHeader.KD_RUANGAN_T) == null ? ""
						: request.getHeader(Constants.HttpHeader.KD_RUANGAN_T);
			   
			   if ("".equals(idRuanganTujuan.trim())){
				   try{
					   JSONObject jObject = new JSONObject(body);
					   ExtractObjectJson(jObject, false);
				   }catch(Exception e){
					   
				   }
			   }
		}
		
		public String getHeader(String key){
			if (key.equals(Constants.HttpHeader.KD_RUANGAN_A)) {
				if (autoIdTujuan.length() > 0){
					return autoIdTujuan.toString();
				}				
			}
			
			return super.getHeader(key);
		}
		
		JSONArray autoIdTujuan = new JSONArray();
		
		void ExtractObjectJson(JSONObject jObject, boolean ruangan) throws Exception{
		   Iterator  iterator = jObject.keys();				   
		   while (iterator.hasNext()){
			   String key = String.valueOf(iterator.next());
			   Object o = jObject.get(key);	 
			   
			   if (key.toLowerCase().contains("ruangan")){				     
				   if (o instanceof Integer){
					   autoIdTujuan.put(o);
				   } else if (o instanceof JSONObject){
					   ExtractObjectJson((JSONObject) o, true);
				   }
			   } else if (ruangan && "id".equals(key)){
				   if (o instanceof Integer){
					   autoIdTujuan.put(o);
					   return;
				   }
			   } else if (o instanceof JSONObject && !ruangan) {
				   ExtractObjectJson((JSONObject) o, false);
			   }
		   }				   
		}
		
		@Override
		public ServletInputStream getInputStream() throws IOException {
			final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
			ServletInputStream servletInputStream = new ServletInputStream() {
				public int read() throws IOException {
					return byteArrayInputStream.read();
				}
			};
			return servletInputStream;
		}

		@Override
		public BufferedReader getReader() throws IOException {
			return new BufferedReader(new InputStreamReader(getInputStream()));
		}

		public String getBody() {
			return this.body;
		}
	}
	// End Syamsu
	

	private final Logger log = LoggerFactory.getLogger(CORSFilter.class);

	public CORSFilter() {
		log.info("CORSFilter JasaMedika Web init");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {

		// Start Syamsu
		RequestWrapper myReq = new RequestWrapper((HttpServletRequest) req);
		// End Syamsu
		HttpServletRequest request = (HttpServletRequest) myReq;
		HttpServletResponse response = (HttpServletResponse) res;

		response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
		response.setHeader("Access-Control-Allow-Credentials", "true");

		response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
		response.setHeader("Access-Control-Max-Age", "3600");
		response.setHeader("Access-Control-Allow-Headers",
				"Content-Type, Accept, X-Requested-With, remember-me, X-AUTH-TOKEN, "
						+ "Supervising, RequestSupervisor, Module, Form, Action, AlamatUrlForm, KdRuangan, KdUser, "
						+ "MandatoriData, idRuanganTujuan, ruanganTujuan");
		response.setHeader("Content-Type", "application/json");
		
		
//		String body = myReq.getBody();
//		if (!"".equals(body.trim())){
//			log.info("\n\n" + myReq.getBody() + "\n");
//		}
		
		chain.doFilter(myReq, res);
	}

	@Override
	public void init(FilterConfig filterConfig) {

	}

	@Override
	public void destroy() {
	}

}