/* FichothequeLib_API - Copyright (c) 2023 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.fichotheque.sphere;

import java.text.ParseException;
import net.fichotheque.SubsetKey;


/**
 *
 * @author Vincent Calame
 */
public final class LoginKey implements Comparable<LoginKey> {

    private final String loginKeyString;
    private final SubsetKey sphereKey;
    private final String login;

    private LoginKey(SubsetKey sphereKey, String login) {
        this.sphereKey = sphereKey;
        this.login = login;
        this.loginKeyString = sphereKey.getSubsetName() + "_" + login;
    }

    public String getLogin() {
        return login;
    }

    public String getSphereName() {
        return sphereKey.getSubsetName();
    }

    public SubsetKey getSphereKey() {
        return sphereKey;
    }

    @Override
    public int hashCode() {
        return this.loginKeyString.hashCode();
    }

    @Override
    public String toString() {
        return this.loginKeyString;
    }

    @Override
    public boolean equals(Object other) {
        if (other == null) {
            return false;
        }
        if (other == this) {
            return true;
        }
        if (other.getClass() != this.getClass()) {
            return false;
        }
        LoginKey otherLoginKey = (LoginKey) other;
        return (otherLoginKey.loginKeyString.equals(this.loginKeyString));
    }

    @Override
    public int compareTo(LoginKey obj) {
        if (obj == this) {
            return 0;
        }
        return this.loginKeyString.compareTo(obj.loginKeyString);
    }

    public static LoginKey parse(SubsetKey subsetKey, String login) throws ParseException {
        if (!subsetKey.isSphereSubset()) {
            throw new IllegalArgumentException("!subsetKey.isSphereSubset()");
        }
        checkLogin(login);
        return new LoginKey(subsetKey, login);
    }

    public static LoginKey build(SubsetKey subsetKey, String login) {
        try {
            return parse(subsetKey, login);
        } catch (ParseException pe) {
            throw new IllegalArgumentException("malformed login");
        }
    }

    public static LoginKey parse(String key) throws ParseException {
        int idx = key.indexOf('[');
        if (idx != -1) {
            return parseBrackets(key);
        }
        idx = key.indexOf('_');
        if (idx != -1) {
            return parseUnderscore(key);
        }
        throw new ParseException("Missing separator (_ or [])", 0);
    }

    private static LoginKey parseBrackets(String key) throws ParseException {
        int idx1 = key.indexOf('[');
        int idx2 = key.indexOf(']');
        if (idx2 < 0) {
            throw new ParseException("Missing ]", 0);
        }
        if (idx2 < idx1) {
            throw new ParseException("] before [", idx2);
        }
        if (idx2 < (key.length() - 1)) {
            throw new ParseException("characters after ]", idx2);
        }
        String login = key.substring(0, idx1).trim();
        String sphereString = key.substring(idx1 + 1, idx2).trim();
        SubsetKey sphereKey = SubsetKey.parse(SubsetKey.CATEGORY_SPHERE, sphereString);
        checkLogin(login);
        return new LoginKey(sphereKey, login);
    }

    private static LoginKey parseUnderscore(String key) throws ParseException {
        int idx = key.indexOf('_');
        if (idx == 0) {
            throw new ParseException("Starting with _", 0);
        }
        if (idx == (key.length() - 1)) {
            throw new ParseException("Ending with _", 0);
        }
        String login = key.substring(idx + 1);
        String sphereString = key.substring(0, idx);
        SubsetKey sphereKey = SubsetKey.parse(SubsetKey.CATEGORY_SPHERE, sphereString);
        checkLogin(login);
        return new LoginKey(sphereKey, login);
    }

    /**
     * Un identifiant de connexion (login) doit répondre à l'expression
     * rationnelle : [a-zA-Z][a-zA-Z0-9]*.
     */
    public static void checkLogin(String login) throws ParseException {
        int length = login.length();
        if (length == 0) {
            throw new ParseException("empty login", 0);
        }
        if (!testFirstChar(login.charAt(0))) {
            throw new ParseException("wrong first char", 0);
        }
        for (int i = 1; i < length; i++) {
            if (!testChar(login.charAt(i))) {
                throw new ParseException("wrong char", i);
            }
        }
    }

    private static boolean testFirstChar(char carac) {
        if ((carac >= 'A') && (carac <= 'Z')) {
            return true;
        } else if ((carac >= 'a') && (carac <= 'z')) {
            return true;
        } else {
            return false;
        }
    }

    private static boolean testChar(char carac) {
        if ((carac >= 'A') && (carac <= 'Z')) {
            return true;
        } else if ((carac >= 'a') && (carac <= 'z')) {
            return true;
        } else if ((carac >= '0') && (carac <= '9')) {
            return true;
        } else {
            return false;
        }
    }


}
