package gov.va.med.ars.sec;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;

/**
 * Model representing the employee
 * 
 * @author Ian Meinert
 * @version 1.0 September 11, 2014
 */
public class AppAuthorization {
	
	/**
	 * logger
	 */
	//private static final Logger logger = Logger.getLogger(AppAuthorization.class.getName());
	
	static final Logger auditLogger = Logger.getLogger("auditLogger");
	
	private String appName;
	
	// This simplifies the use of JDBC and helps to avoid common errors.
	private JdbcTemplate jdbcTemplate;
	private SimpleJdbcCall simpleJdbcCall;

	private AppUser user;
	private String ntusername;

	/**
	 * Default constructor
	 * 
	 * @param dataSource
	 *            datasource wired in from the servlet configuration.
	 */
	
	public AppAuthorization(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
		this.simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate);
		this.user = null;
	}

	public AppAuthorization() {
		super();
	}

	/**
	 * This begins the authorization process. It will generate a list of users
	 * and then filter out all the users that do not match the client
	 * information.
	 * 
	 * @param appName
	 *            the name of the application
	 * @return if the client is authorized
	 */
	public boolean isAuthorized() {
		
		auditLogger.trace("Get the users authorized access for the application");
		List<AppUser> users = getAppUsers();
		List<String> roles = new ArrayList<String>();
		AppUser foundUser = new AppUser();

		auditLogger.trace("Only search for a user if it the list is not empty");
		if (!users.isEmpty()) {
			auditLogger.trace("Iterate over the AppUsers");
			for (AppUser user : users) {
				auditLogger.trace("An AppUser is found with the requesting client");
				if (user.getNtusername().equals(this.ntusername)) {
					
					foundUser = user;
					
					auditLogger.trace("Build the roles for the current user");
					roles.add(user.getRole());
				}
			}
			
			foundUser.setRoles(roles);
		}
		this.user = foundUser;
		
		return (user.getAuthorities().size() > 0);
	}

	/**
	 * Performs a basic retrieval operation to generate a list of AppUser's that
	 * are authorized access to the provided application name.
	 * 
	 * @param appName
	 *            the name of the application
	 * @return list of authorized AppUser's
	 */
	@SuppressWarnings("unchecked")
	private List<AppUser> getAppUsers() {

		auditLogger.debug("Application name is: " + appName);
		List<AppUser> users = new ArrayList<AppUser>();

		/*this.simpleJdbcCall.setProcedureName("GetUserRoles");

		Map<String, String> inputParamater = new HashMap<>();
		inputParamater.put("ApplicationName", appName);
		simpleJdbcCall.returningResultSet("result", new RowMapper<AppUser>() {

			@Override
			public AppUser mapRow(ResultSet rs, int rowNum) throws SQLException {
				auditLogger.trace("Spring security needs the ROLE_ prefix to recognize the roles from the database as being a system role. So add it to the role");
				String role = "ROLE_" + rs.getString("rolename").replace(" ", "_").toUpperCase();
				
				AppUser appUser = new AppUser(rs.getString("name"), role, rs.getString("ntusername"));
				
				auditLogger.debug(appUser.getNtusername());
				auditLogger.debug(appUser.getName());
				auditLogger.debug(appUser.getRole());
				
				return appUser;
			}
		});

		Map<String, Object> response = simpleJdbcCall.execute(inputParamater);*/
		
		AppUser appUser = new AppUser(this.ntusername, "ROLE_USER", this.ntusername);

		//auditLogger.debug("found " + response.size() + " user(s)");

/*		for (Map.Entry<String, Object> entry : response.entrySet()) {		
			users.addAll((Collection<AppUser>) entry.getValue());
		}*/
		
		users.add(appUser);

		return users;
	}
	
	public AppUser getUser() {
		return user;
	}

	public String getNtusername() {
		return ntusername;
	}

	public void setNtusername(String ntusername) {
		this.ntusername = ntusername;
	}
	
	public void setAppName(String appName) {
		this.appName = appName;
	}
	
	public static boolean isNumeric(String str) {
		auditLogger.trace("Catch a number with optional.");
		return str.matches("\\d+?"); 
	}
}