/*
 * Profile.java
 *
 * Autor: Karolina Sołtys
 */
package dendrarium.portal.profile;

import dendrarium.core.entities.Role;
import dendrarium.core.entities.User;
import dendrarium.trees.xml.ForestExportFormat;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hibernate.Session;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.FlushModeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.RaiseEvent;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Identity;

/**
 *
 * @author Karolina Sołtys
 */
@Name("profile")
@Scope(ScopeType.CONVERSATION)
public class Profile implements Serializable {

    @In
    Identity identity;

    @In
    Session session;

    @In
    @Out(required = false)
    User user;

    @Logger
    Log log;

    @In(required = false)
    @Out
    User userProfile;

    @In
    private FacesMessages facesMessages;

    @Out
    boolean canEdit;

    @In(required = false)
    @Out(required = false)
    List<RoleEntry> roles;

    String verify;

    @Begin(join = true, flushMode = FlushModeType.MANUAL)
    public void select(User userProfile) {
        this.userProfile = userProfile;
        canEdit = user.getUsername().equals(userProfile.getUsername()) || identity.hasRole("admin");
    }

    @Factory("userProfile")
    public User getDefaultUser() {
        this.userProfile = user;
        canEdit = true;
        return user;
    }

    @Factory
    public void getRoles() {
        if (userProfile == null) {
            getDefaultUser();
        }

        userProfile = (User) session.merge(userProfile);
        List<Role> allRoles = session.createCriteria(Role.class).list();

        roles = new ArrayList<RoleEntry>();
        for (Role role : allRoles) {
            RoleEntry entry = new RoleEntry(userProfile.getRoles().contains(role), role);
            roles.add(entry);
        }
    }

    public void changeRoles() {
        userProfile = (User) session.merge(userProfile);
        for (RoleEntry entry : roles) {
            Role role = (Role) session.merge(entry.role);

            if (!entry.value && userProfile.getRoles().contains(role)) {
                facesMessages.add("Odebrano rolę " + role.getRolename() + " uzytkownikowi " + userProfile.getUsername());
                userProfile.getRoles().remove(role);
            } else if (entry.value && !userProfile.getRoles().contains(role)) {
                facesMessages.add("Nadano rolę " + role.getRolename() + " uzytkownikowi " + userProfile.getUsername());
                userProfile.getRoles().add(role);
            }
        }
        if (userProfile.getUsername().equals(user.getUsername())) {
            this.user = userProfile;
        }

        session.flush();
    }

    public void changePassword() {
        if (userProfile.getPassword().equals(verify)) {
            userProfile = (User) session.merge(userProfile);
            if (userProfile.getUsername().equals(user.getUsername())) {
                this.user = userProfile;
            }

            session.flush();
            facesMessages.add("Hasło zostało zmienione");
        } else {
            facesMessages.addToControl("verify", "Spróbuj jeszcze raz");
            revertUser();
        }
    }

    private void revertUser() {
        userProfile = (User) session.get(User.class, userProfile.getUsername());
    }

    public void setVerify(String verify) {
        this.verify = verify;
    }

    public String getVerify() {
        return verify;
    }

    @RaiseEvent("userListChange")
    public void cancel() {
        revertUser();
    }

    @End
    @RaiseEvent("userListChange")
    public void update() {
        session.merge(userProfile);
        if (userProfile.getUsername().equals(user.getUsername())) {
            this.user = userProfile;
        }
        session.flush();
    }
}
