package enea.lecservice.security;

import enea.lecservice.security.dto.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.log.LogMessage;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.core.userdetails.memory.UserAttribute;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class InMemoryUserInfoService {
    private final Map<String, UserInfo> users = new HashMap<>();
    private AuthenticationManager authenticationManager;


    /*public ENEAUserDetailsService(UserDetails... users) {
        UserDetails[] var2 = users;
        int var3 = users.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            UserDetails user = var2[var4];
            this.createUser(user);
        }

    }

    public ENEAUserDetailsService(Properties users) {
        Enumeration<?> names = users.propertyNames();
        UserAttributeEditor editor = new UserAttributeEditor();

        while(names.hasMoreElements()) {
            String name = (String)names.nextElement();
            editor.setAsText(users.getProperty(name));
            UserAttribute attr = (UserAttribute)editor.getValue();
            this.createUser(this.createUserDetails(name, attr));
        }

    }*/

    /*private User createUserDetails(String name, UserAttribute attr) {
        return new User(name, attr.getPassword(), attr.isEnabled(), true, true, true, attr.getAuthorities());
    }*/


    public void createRemovingIfExists(UserInfo user) {
        if (this.userExists(user.getUsername()))
            this.deleteUser(user.getUsername());
        this.users.put(user.getUsername().toLowerCase(), user);
        //this.users.put(user.getUsername().toLowerCase(), new UserInfo(user));
    }

    /*public void createUser(UserInfo user) {
        Assert.isTrue(!this.userExists(user.getUsername()), "user should not exist");
        this.users.put(user.getUsername().toLowerCase(), user);
        //this.users.put(user.getUsername().toLowerCase(), new UserInfo(user));
    }

    public void updateUser(UserInfo user) {
        Assert.isTrue(this.userExists(user.getUsername()), "user should exist");
        this.users.put(user.getUsername().toLowerCase(), user);
        //this.users.put(user.getUsername().toLowerCase(), new UserInfo(user));
    }*/

    public void deleteUser(String username) {
        this.users.remove(username.toLowerCase());
    }

    public boolean userExists(String username) {
        return this.users.containsKey(username.toLowerCase());
    }

    /*public void changePassword(String oldPassword, String newPassword) {
        Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
        if (currentUser == null) {
            throw new AccessDeniedException("Can't change password as no Authentication object found in context for current user.");
        } else {
            String username = currentUser.getName();
            this.logger.debug(LogMessage.format("Changing password for user '%s'", username));
            if (this.authenticationManager != null) {
                this.logger.debug(LogMessage.format("Reauthenticating user '%s' for password change request.", username));
                this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword));
            } else {
                this.logger.debug("No authentication manager set. Password won't be re-checked.");
            }

            UserInfo user = (UserInfo)this.users.get(username);
            Assert.state(user != null, "Current user doesn't exist in database.");
            user.setPassword(newPassword);
        }
    }*/

    /*public UserDetails updatePassword(UserDetails user, String newPassword) {
        String username = user.getUsername();
        UserInfo mutableUser = (UserInfo) this.users.get(username.toLowerCase());
        mutableUser.setPassword(newPassword);
        return mutableUser;
    }*/

    public UserInfo loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo user = this.users.get(username.toLowerCase());
        if (user == null) {
            throw new UsernameNotFoundException(username);
        } else {
            //return new User(user.getUsername(), user.getPassword(), user.isEnabled(), user.isAccountNonExpired(), user.isCredentialsNonExpired(), user.isAccountNonLocked(), user.getAuthorities());
            return user;
        }
    }

    /*public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }*/
}
