
//import it.inaf.ia2.aa.data.User;

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*; // ArrayList<String> Collection<>

import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;


import javax.servlet.http.HttpServletRequestWrapper;
import java.security.Principal;


/* response wrapper */

import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.ServletOutputStream;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayOutputStream;



class AuthZ
{
   private static final Logger LOGGER = Logger.getLogger(AuthZ.class.getName());
   private static final AuthZSettings settings = AuthZSettings.getInstance("authpolicy.properties");

   List<String> pubdidList = new ArrayList<String>();

   String requestPath;


	// collect ID's in request to pubdidList
   public AuthZ(HttpServletRequest req) throws IOException, ServletException
   {
      LOGGER.fine("constructor");

      requestPath = req.getRequestURI();
      LOGGER.fine("Req.Path: " + requestPath);

      String[] pubdidArr = req.getParameterValues("ID");

      if(pubdidArr == null)
      {
         LOGGER.fine("No ID found in request params");
      }
      else
      {
         for(String pubdid : pubdidArr)
            if(pubdid.length() > 0) pubdidList.add(pubdid);

         LOGGER.finest("Request IDs: " + String.join(" ", pubdidList));
      }
   }


   public boolean isAuthorized(HttpServletRequest req)
   {
      LOGGER.fine("isAuthorized");

      AuthPolicy auth = null;
      try
      {
         auth = new AuthPolicy(req.getUserPrincipal());
      }
      catch(IllegalArgumentException ex)
      {
         throw new IllegalArgumentException("Authorization : UserPrincipal is not of expected type");
      }

      String[] pubdidArr = pubdidList.toArray(new String[pubdidList.size()]);
		String[] authorizedPubdids = auth.removeNotAuthorized(pubdidArr);
		// none of above must result in null

		LOGGER.finest("authorized vs original length: " + authorizedPubdids.length + " / " + pubdidArr.length);

		if(requestPath.contains("async"))
			return auth.isUserInGroup("VLKB.AllPrivate");// FIXME workaround for mcutout request
		else
			return (authorizedPubdids.length == pubdidArr.length); // SODA request

		/* NOTE: If multiplicity allowed like in mcutout/merge:
		 * if one or more of pubdids not-authorized -> all request not authorized
		 * SODA does not allow multiplicity, has only one ID */
	}

}





@javax.servlet.annotation.MultipartConfig
public class AuthZFilter implements Filter
{
	private static final Logger LOGGER = Logger.getLogger(AuthZFilter.class.getName());


	@Override
		public void init(FilterConfig fc) throws ServletException {}

	@Override
		public void destroy() {}

	@Override
		public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
		throws IOException, ServletException
		{
			LOGGER.fine("doFilter");

			HttpServletRequest  req  = (HttpServletRequest)  request;
			HttpServletResponse  resp = (HttpServletResponse)  response;

			AuthZ authz = new AuthZ(req);

			if(authz.isAuthorized(req))
			{
				LOGGER.fine("Decision: Authorized, pass to servlet");
				chain.doFilter(request, response);
			}
			else
			{
				LOGGER.fine("Decision: Not Authorized, return FORBIDDEN");
				resp.setContentType("text/plain");
				// FIXME use VO errors vlkb-volib: implement Lib.doPermissionError()...
				resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden");
			}
		}

}

