package it.enea.cruise.model.user;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.Fetch;

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonManagedReference;

@Entity(name = "olduser")
@Table(name = "Users")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OldUser {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long userid;

	@JsonAlias({ "preferred_username", "username" })
	private String username;

	@OneToMany(
			mappedBy = "user",
			cascade = CascadeType.ALL, 
			fetch=FetchType.EAGER)
	@JsonManagedReference(value = "user-communities")
	@Fetch(value = FetchMode.SUBSELECT)
	//@JoinColumn(name="userid")
	private List<UserCommunity> userCommunities = new ArrayList<UserCommunity>();
	
		@OneToMany(mappedBy = "user",
			cascade = CascadeType.ALL, 
			fetch=FetchType.EAGER)
	@Fetch(value = FetchMode.SUBSELECT)
	@JsonManagedReference(value = "user-userRoles")
	private List<UserRole> userRoles = new ArrayList<UserRole>();
	
//	@ManyToMany(fetch=FetchType.EAGER)
//	@JoinTable(name = "users_roles", 
//		joinColumns = @JoinColumn(name = "userid", 
//		referencedColumnName = "userid"), 
//		inverseJoinColumns = @JoinColumn(name = "roleid", referencedColumnName = "id"))
//	@Fetch(value = FetchMode.SUBSELECT)
	
	@Transient
	private List<Role> roles = new ArrayList<Role>();
	
	@JsonAlias({ "lastname", "family_name", "usersurname", "lastName" })
	@Column(name = "usersurname")
	private String lastName;
	
	@JsonAlias({ "given_name", "name" })
	@Column(name = "userfirstname")
	private String userFirstName;

	@Column(name = "subject")
	private String subject;

	@Transient
	private String password;

	private String address;
	private String zip;
	private String city;
	private String province;
	private String fiscalcode;

	@JsonAlias({ "email" })
	private String email;

	@Transient
	@JsonAlias({ "community", "communityId" })
	private Long tmpCommunity;
	@Transient
	private String tmpWallet;

	@Transient
	@JsonAlias({ "GDPR", "gdpr" })
	private boolean gdpr;

	@Transient
	@JsonAlias({ "roles", "gdpr" })
	private List<String> role;

	@Transient
	@JsonIgnore
	private String token;

	@Transient
	@JsonIgnore
	private List<String> keycloakRoles;

	

	public OldUser() {
	}

	public OldUser(String username) {
		this.username = username;
	}

	/**
	 * Questo metodo permette di associare un utente ad una comunita'. Da notare che
	 * la nuova comunita' e' associata sia nell'oggetto User sia nell'oggetto
	 * UserCommunities associato alla Comunita'.
	 */
//	public UserCommunity addCommunity(Community g) {
//		UserCommunity ug = new UserCommunity(this, g);
//		userCommunities.add(ug);
//		g.getUserCommunities().add(ug);
//		return ug;
//	}
//	
	/**
	 * Questo metodo permette di associare un utente ad una comunita'. Da notare che
	 * la nuova comunita' e' associata sia nell'oggetto User sia nell'oggetto
	 * UserCommunities associato alla Comunita'.
	 */
	//public UserRole addRole(Role r) {
	//	System.out.println (r.getDescription());
	//	UserRole ur = new UserRole(this, r, this.tmpCommunity);
	//	userRoles.add(ur);
	//	r.getUserRoles().add(ur);
	//	return ur;
	//}

//	@Override
//	public boolean equals(Object o) {
//		if (this == o)
//			return true;
//		if (o == null || getClass() != o.getClass())
//			return false;
//		User u = (User) o;
//		return Objects.equals(username, u.username);
//	}

	@Override
	public int hashCode() {
		return Objects.hash(username);
	}

	public Long getUserid() {
		return userid;
	}

	public void setUserid(Long userid) {
		this.userid = userid;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public List<UserCommunity> getUserCommunities() {
		return userCommunities;
	}

	public void setUserCommunities(List<UserCommunity> userCommunities) {
		this.userCommunities = userCommunities;
	}
	
	public String getUserfirstname() {
		return userFirstName;
	}

	public void setUserfirstname(String userFirstName) {
		this.userFirstName = userFirstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getSubject() {
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getZip() {
		return zip;
	}

	public void setZip(String zip) {
		this.zip = zip;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getProvince() {
		return province;
	}

	public void setProvince(String province) {
		this.province = province;
	}

	public String getFiscalcode() {
		return fiscalcode;
	}

	public void setFiscalcode(String fiscalcode) {
		this.fiscalcode = fiscalcode;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public Long getTmpCommunity() {
		return tmpCommunity;
	}

	public void setTmpCommunity(Long tmpCommunity) {
		this.tmpCommunity = tmpCommunity;
	}

	public String getTmpWallet() {
		return tmpWallet;
	}

	public void setTmpWallet(String tmpWallet) {
		this.tmpWallet = tmpWallet;
	}

//	public User merge(User userTemp) {
//		this.email = userTemp.email;
//		this.lastName = userTemp.lastName;
//		this.subject = userTemp.subject;
//		this.tmpCommunity = userTemp.tmpCommunity;
//		this.tmpWallet = userTemp.tmpWallet;
//		this.username = userTemp.username;
//
//		return this;
//	}

	public boolean getGdpr() {
		return gdpr;
	}

	public void setGdpr(boolean gDPRApproval) {
		gdpr = gDPRApproval;
	}

	public List<Role> getRoles() {
		return roles;
	}

	public void setRoles(List<Role> roles) {
		this.roles = roles;
	}

	public void setKeycloakRoles(List<String> roles) {
		this.keycloakRoles = roles;
	}

	public List<String> getKeycloakRoles() {
		return this.keycloakRoles;
	}

//	public void addRoles(List<Role> roles) {
//		for (Role role : roles) {
//			if (!this.roles.contains(role)) {
//				this.roles.add(role);
//			}
//		}
//	}
	
	

	public void clearRoles() {
		this.userRoles.clear();
	}
	
	public void clearCommmunities() {
		this.userCommunities.clear();
	}

	public void addRole(Role role) {
		this.roles.add(role);

	}
	
	public boolean hasRole (String roleName) {
		boolean result = false;
		for (UserRole ur : userRoles) {
			if (ur.getRole().getRolename().equals(roleName)) {
				result =  true;
			}
		}
		return result;
	}
	
	public void addUserRole (UserRole ur) {
		if (this.userRoles == null) this.userRoles = new ArrayList<UserRole>();
		this.userRoles.add(ur);
		if (this.roles == null) this.roles = new ArrayList<Role>();
		this.roles.add(ur.getRole());
	}
	
	public void setSingleUsercommunity(UserCommunity uc) {
		Boolean exists = false;
		for (UserCommunity c : this.userCommunities) {
			if (c.getId().equals(uc.getId())) {
				exists = true;
			}
		}
		
		if (!exists)
		this.userCommunities.add(uc);
	}
	
//	public void addUserRoleInCommunity (Role r, Community c) {
//		if (this.userRoles == null) this.userRoles = new ArrayList<UserRole>();
//		UserRole ur = new UserRole();
//		ur.setUser(this);
//		ur.setRole(r);
//		ur.setCommunity(c);
//		this.userRoles.add(ur);
//	}

	public List<UserRole> getUserRoles() {
		return userRoles;
	}

	public void setUserRoles(List<UserRole> userRoles) {
		this.userRoles = userRoles;
		if (this.roles == null) this.roles = new ArrayList<Role>();

		for (UserRole ur : userRoles) {
			this.roles.add(ur.getRole());
		}
	}
	
	

}
