package adecWatt.model;

import java.util.HashSet;
import java.util.Hashtable;

import misc.Config;
import misc.StateNotifier;
import misc.Util;

public class User extends StateNotifier {

    // ========================================
    static public final int serverId = 0;
    static public final int visitorId = 1;
    static public final String
	BroadcastUserChangeProfil		= "UserChangeProfil";

    static public enum Role {
	// import/export/print
	Visitor, // afficher
	StageManager, // créer/modifier/organiser des plans de feu
	Architect, // créer/modifier/organiser des leux/salles
	FurnitureManager, // créer/modifier/organiser des mobilier accessoires et des informations
	Linguist, // traduction des formulaires (tout voir avec affiche)
	DataStructuresManager, // ajout de champs et métamorphose
	DataManager, // transfert sur le serveur
	Yoda; // depasé les bornes, il n'y a plus de limite
    }

    // ========================================
    public boolean connected = false;
    private String login, password;
    private int currentId;
    private int userId;
    private Hashtable<Integer, Integer> maxIds = new Hashtable<> ();
    private HashSet<Role> roles = new HashSet<Role> ();

    static public int updateRoles (HashSet<Role> roles, String rolesLine) {
	roles.clear ();
	roles.add (Role.Visitor);
	try {
	    String[] tokens = rolesLine.split ("\\|");
	    String id = tokens [0];
	    tokens = tokens[1].split (",");
	    for (String token : tokens)
		try {
		    roles.add (Role.valueOf (Role.class, token));
		} catch (Exception e) {
		    e.printStackTrace ();
		}
	    return Integer.parseInt (id);
	} catch (Exception e) {
	    return visitorId;
	}
    }
    public HashSet<Role> getRoles () { return new HashSet<Role> (roles); }
    public String  getLogin ()			{ return login; }
    public String  getPassword ()		{ return password; }
    public int	   getUserId ()			{ return userId; }
    public boolean isVisitorId ()		{ return userId == 1; }

    // ========================================
    public boolean hasRole (Role... someRoles) {
	for (Role role : someRoles)
	    if (roles.contains (role))
		return true;
	return false;
    }
    public boolean isAdmin ()			{ return hasRole (Role.Yoda); }
    public boolean isLinguist ()		{ return hasRole (Role.Linguist) || isAdmin (); }
    public boolean isDataStructuresManager ()	{ return hasRole (Role.DataStructuresManager) || isAdmin (); }
    public boolean isDataManager ()		{ return hasRole (Role.DataManager) || isAdmin (); }
    public boolean isEditor () {
	return
	    hasRole (Role.StageManager) ||
	    hasRole (Role.Architect) ||
	    hasRole (Role.FurnitureManager) || isAdmin ();
    }
    public boolean isEditor (Unit<?> unit) {
	try {
	    if (isAdmin ())
		return true;
	    switch (Permanent.UnitTypeEnum.valueOf (Permanent.UnitTypeEnum.class, Util.toCapital (unit.getUnitRoot ().getName ()))) {
	    case Lightplot:
		return hasRole (Role.StageManager);
	    case Furniture:
	    case Information:
	    case Line:
	    case Accessory:
		return hasRole (Role.FurnitureManager);
	    case Building:
		return hasRole (Role.Architect);
	    }
	} catch (Exception e) {
	}
	return false;
    }

    // ========================================
    private void getConfig (Role role) {
	if (Config.getBoolean ("Role"+role, false))
	    roles.add (role);
    }
    private void setConfig (Role role) {
	Config.setBoolean ("Role"+role, roles.contains (role));
    }

    // ========================================
    public User () {
	currentId = userId = Config.getInt ("UserId", visitorId);
	login = Config.getString ("Login", "");
	roles.add (Role.Visitor);
	getConfig (Role.StageManager);
	getConfig (Role.Architect);
	getConfig (Role.FurnitureManager);
    }

    // ========================================
    public void setLogin (String login) {
	Config.setString ("Login", this.login = login);
    }
    public void setPassword (String password) {
	this.password = password;
    }

    // ========================================
    public void setRoles (HashSet<Role> roles) {
	this.roles = new HashSet<Role> (roles);
	this.roles.add (Role.Visitor);
	currentId = isDataManager () ? serverId : userId;
	setConfig (Role.StageManager);
	setConfig (Role.Architect);
	setConfig (Role.FurnitureManager);
	broadcastUpdate (BroadcastUserChangeProfil);
    }
    public void setUserId (int userId) {
	this.userId = userId;
	Config.setInt ("UserId", userId);
	currentId = isDataManager () ? serverId : userId;
    }

    // ========================================
    static public String getDataId (int ownerId, int serialId) {
	return String.format ("%03d-%04d", ownerId, serialId);
    }
    static public int[] splitId (String id) {
	try {
	    if (id == null)
		return null;
	    int sepIdx = id.indexOf ("-");
	    int ownerId = Integer.parseInt (id.substring (0, sepIdx));
	    int extIdx = id.indexOf (".", sepIdx);
	    int value = Integer.parseInt (extIdx > 0 ? id.substring (sepIdx+1, extIdx) : id.substring (sepIdx+1));
	    return new int [] {ownerId, value};
	} catch (Exception e) {
	}
	return null;
    }

    // ========================================
    public String getDataId () {
	int maxId = 0;
	try {
	    maxId = maxIds.get (currentId);
	} catch (Exception e) {
	}
	maxId++;
	maxIds.put (currentId, maxId);
	return getDataId (currentId, maxId);
    }
    public void updateDataId (String id) {
	int [] ids = splitId (id);
	if (ids == null)
	    return;
	int ownerId = ids[0];
	int value = ids[1];
	int maxId = 0;
	try {
	    maxId = maxIds.get (ownerId);
	} catch (Exception e) {
	}
	if (value > maxId)
	    maxIds.put (ownerId, value);
    }

    // ========================================
}
