package fr.icl.picsel20.user.store;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.user.api.Properties;
import org.wso2.carbon.user.api.Property;
import org.wso2.carbon.user.api.RealmConfiguration;
import org.wso2.carbon.user.core.UserCoreConstants;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.core.UserStoreException;
import org.wso2.carbon.user.core.claim.ClaimManager;
import org.wso2.carbon.user.core.common.AbstractUserStoreManager;
import org.wso2.carbon.user.core.common.RoleContext;
import org.wso2.carbon.user.core.profile.ProfileConfigurationManager;
import org.wso2.carbon.user.core.tenant.Tenant;

public class CustomUserStoreManager extends AbstractUserStoreManager {

	private static Log LOGGER = LogFactory.getLog(CustomUserStoreManager.class);
	protected DataSource jdbcds = null;

	public CustomUserStoreManager() {
		readGroupsEnabled = true;
		writeGroupsEnabled = false;
	}

	public CustomUserStoreManager(RealmConfiguration realmConfig, Map<String, Object> properties,
			ClaimManager claimManager, ProfileConfigurationManager profileManager, UserRealm realm, Integer tenantId)
			throws UserStoreException {
		this.realmConfig = realmConfig;
		this.tenantId = tenantId;
		this.readGroupsEnabled = true;
		writeGroupsEnabled = false;
	}
	@Override
	public boolean isSharedGroupEnabled() {
		return true;
	}

	public CustomUserStoreManager(RealmConfiguration realmConfig, ClaimManager claimManager,
			ProfileConfigurationManager profileManager) throws UserStoreException {
	}

	@Override
	public boolean doAuthenticate(String userName, Object credential) throws UserStoreException {
		if (StringUtils.isEmpty(userName)) {
			return false;
		}

		return true;
	}

	public String[] getAllProfileNames() throws UserStoreException {
		return new String[] { UserCoreConstants.DEFAULT_PROFILE };
	}

	public String[] getProfileNames(String userName) throws UserStoreException {
		return new String[] { UserCoreConstants.DEFAULT_PROFILE };
	}

	@Override
	public Map<String, String> getUserPropertyValues(String arg0, String[] arg1, String arg2)
			throws UserStoreException {
		LOGGER.info("getUserPropertyValues()");

		return new HashMap<>();
	}

	@Override
	public boolean doCheckExistingRole(String roleName) throws UserStoreException {
		LOGGER.info("doCheckExistingRole()");
		return StringUtils.isEmpty(getRoleByName(roleName));
	}

	// @Override
	public boolean doCheckExistingUser(String arg0) throws UserStoreException {
		// TODO: add user to cache
		LOGGER.info("doCheckExistingUser()");

		return true;
	}

	@Override
	public String[] doListUsers(String filter, int maxItemLimit) throws UserStoreException {
		LOGGER.info("doListUsers()");
		return new String[]{"Lala", "Toto", "Titi", "Jeje"};
	}

	@Override
	protected String[] doGetDisplayNamesForInternalRole(String[] userNames) throws UserStoreException {
		LOGGER.info("doGetDisplayNamesForInternalRole()");
		return userNames;
	}

	public void doAddRole(String roleName, String[] userList, boolean shared) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	public void doUpdateRoleName(String roleName, String newRoleName) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	public boolean isBulkImportSupported() {
		return false;
	}

	public boolean isMultipleProfilesAllowed() {
		return false;
	}

	public void doDeleteRole(String roleName) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	public String[] doGetRoleNames(String filter, int maxItemLimit) throws UserStoreException {
		LOGGER.info("doGetRoleNames(): " + readGroupsEnabled);
		return new String[] {"Role 1", "Role 2", "Role 3"};
	}

	@Override
	protected String[] doGetSharedRoleNames(String arg0, String arg1, int arg2) throws UserStoreException {
		LOGGER.info("doGetSharedRoleNames()");
		return new String[] {};
	}

	@Override
	public String[] doGetUserListOfRole(String roleName, String filter) throws UserStoreException {
		LOGGER.info("doGetUserListOfRole()");
		return new String[] {};
	}

	@Override
	public String[] doGetExternalRoleListOfUser(String username, String filter) throws UserStoreException {
		LOGGER.info("doGetExternalRoleListOfUser()");
		if ("Lala".equals(username)) {
			return new String[]{"Role 1"};
		} else {
			return new String[] {"Role 2"};
		}
	}

	@Override
	protected String[] doGetSharedRoleListOfUser(String userName, String tenantDomain, String filter)
			throws UserStoreException {
		LOGGER.info("doGetSharedRoleListOfUser()");
		return doGetExternalRoleListOfUser(userName, filter);
	}

	public boolean isReadOnly() throws UserStoreException {
		return true;
	}

	@Override
	public String[] getUserListFromProperties(String arg0, String arg1, String arg2) throws UserStoreException {
		LOGGER.info("getUserListFromProperties()");
		throw new UserStoreException("Invalid operation");
	}

	@Override
	public boolean doCheckIsUserInRole(String userName, String roleName) throws UserStoreException {
		LOGGER.info("doCheckIsUserInRole()");
		return true;
	}

	@Override
	public String[] getRoleListOfUser(String arg0) throws UserStoreException {
		LOGGER.info("getRoleListOfUser()");
		return super.getRoleListOfUser(arg0);
	}

	@Override
	public Properties getDefaultUserStoreProperties() {
		Properties properties = new Properties();
		properties.setMandatoryProperties(CustomUserStoreProperties.MANDATORY_PROPERTIES
				.toArray(new Property[CustomUserStoreProperties.MANDATORY_PROPERTIES.size()]));
		properties.setOptionalProperties(CustomUserStoreProperties.OPTIONAL_PROPERTIES
				.toArray(new Property[CustomUserStoreProperties.OPTIONAL_PROPERTIES.size()]));
		properties.setAdvancedProperties(CustomUserStoreProperties.ADVANCED_PROPERTIES
				.toArray(new Property[CustomUserStoreProperties.ADVANCED_PROPERTIES.size()]));
		return properties;
	}

	private String getRoleByName(String name) throws UserStoreException {
		LOGGER.info("getRoleByName()");
		return "";
	}

	@Override
	public Map<String, String> getProperties(Tenant arg0) throws UserStoreException {
		return this.realmConfig.getUserStoreProperties();
	}

	@Override
	public RealmConfiguration getRealmConfiguration() {
		return this.realmConfig;
	}

	@Override
	public int getTenantId() throws UserStoreException {
		return this.tenantId;
	}

	@Override
	public int getTenantId(String username) throws UserStoreException {
		throw new UserStoreException("Invalid operation");
	}

	@Override
	public int getUserId(String username) throws UserStoreException {
		throw new UserStoreException("Invalid operation");
	}

	@Override
	public void addRememberMe(String arg0, String arg1) throws org.wso2.carbon.user.api.UserStoreException {
		throw new UserStoreException("Invalid operation");
	}

	@Override
	public Map<String, String> getProperties(org.wso2.carbon.user.api.Tenant tenant)
			throws org.wso2.carbon.user.api.UserStoreException {
		return getProperties((Tenant) tenant);
	}

	@Override
	public boolean isValidRememberMeToken(String arg0, String arg1) throws org.wso2.carbon.user.api.UserStoreException {
		throw new UserStoreException("Invalid operation");
	}

	@Override
	protected RoleContext createRoleContext(String arg0) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doAddUser(String arg0, Object arg1, String[] arg2, Map<String, String> arg3, String arg4,
			boolean arg5) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doDeleteUser(String arg0) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doDeleteUserClaimValue(String arg0, String arg1, String arg2) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doDeleteUserClaimValues(String arg0, String[] arg1, String arg2) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doSetUserClaimValue(String arg0, String arg1, String arg2, String arg3) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doSetUserClaimValues(String arg0, Map<String, String> arg1, String arg2) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doUpdateCredential(String arg0, Object arg1, Object arg2) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");

	}

	@Override
	protected void doUpdateCredentialByAdmin(String arg0, Object arg1) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doUpdateRoleListOfUser(String arg0, String[] arg1, String[] arg2) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	@Override
	protected void doUpdateUserListOfRole(String arg0, String[] arg1, String[] arg2) throws UserStoreException {
		throw new UserStoreException("User store is operating in read only mode. Cannot write into the user store.");
	}

	//
}
