/* BdfServer - Copyright (c) 2006-2024 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 fr.exemole.bdfserver.tools.users;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.instruction.BdfParameters;
import fr.exemole.bdfserver.api.managers.PermissionManager;
import fr.exemole.bdfserver.api.namespaces.BdfUserSpace;
import fr.exemole.bdfserver.api.roles.Role;
import fr.exemole.bdfserver.api.users.BdfUser;
import fr.exemole.bdfserver.api.users.BdfUserConstants;
import fr.exemole.bdfserver.tools.instruction.DefaultBdfParameters;
import java.text.ParseException;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.fichotheque.corpus.SortConstants;
import net.fichotheque.exportation.transformation.TemplateKey;
import net.fichotheque.exportation.transformation.TransformationKey;
import net.fichotheque.namespaces.TransformationSpace;
import net.fichotheque.sphere.Redacteur;
import net.fichotheque.sphere.Sphere;
import net.mapeadores.opendocument.io.SheetWriter;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.attr.AttributeKey;
import net.mapeadores.util.attr.Attributes;
import net.mapeadores.util.text.TypoOptions;
import net.mapeadores.util.text.ValidExtension;


/**
 *
 * @author Vincent Calame
 */
public final class BdfUserUtils {

    public final static Pattern STORE_KEY_PATTERN = Pattern.compile("^[-_\\.a-zA-Z0-9]+$");
    public final static Pattern STORE_NAME_PATTERN = Pattern.compile("^[a-z][-_a-z0-9]*$");

    private BdfUserUtils() {
    }

    public static boolean isAdmin(BdfServer bdfServer, BdfUser bdfUser) {
        return bdfServer.getPermissionManager().isAdmin(bdfUser.getRedacteur());
    }

    public static boolean isSame(BdfUser bdfUser, Redacteur redacteur) {
        return bdfUser.getRedacteur().getGlobalId().equals(redacteur.getGlobalId());
    }

    public static boolean hasRole(PermissionManager permissionManager, BdfUser bdfUser, Role role) {
        return hasRole(permissionManager, bdfUser.getRedacteur(), role.getName());
    }

    public static boolean hasRole(PermissionManager permissionManager, Redacteur redacteur, String roleName) {
        for (Role role : permissionManager.getRoleList(redacteur)) {
            if (role.getName().equals(roleName)) {
                return true;
            }
        }
        return false;
    }

    public static BdfParameters getFirstAdminBdfParameters(BdfServer bdfServer) {
        return new DefaultBdfParameters(bdfServer, getFirstAdminBdfUser(bdfServer));
    }

    public static BdfUser getFirstAdminBdfUser(BdfServer bdfServer) {
        PermissionManager permissionManager = bdfServer.getPermissionManager();
        for (Sphere sphere : bdfServer.getFichotheque().getSphereList()) {
            for (Redacteur redacteur : sphere.getRedacteurList()) {
                if (permissionManager.isAdmin(redacteur)) {
                    return bdfServer.createBdfUser(redacteur);
                }
            }
        }
        throw new IllegalStateException("No redacteur admin");
    }

    public static TemplateKey getSimpleTemplateKey(BdfParameters bdfParameters, TransformationKey transformationKey) {
        String userTemplateName = bdfParameters.getBdfUser().getPrefs().getSimpleTemplateName(transformationKey);
        TemplateKey templateKey = null;
        if (userTemplateName != null) {
            try {
                templateKey = TemplateKey.parse(transformationKey, userTemplateName);
            } catch (ParseException pe) {

            }
        }
        if (templateKey == null) {
            templateKey = resolveDefaultTemplate(bdfParameters, transformationKey, null);
        }
        if (templateKey == null) {
            templateKey = TemplateKey.toDefault(transformationKey);
        }
        return templateKey;
    }

    public static TemplateKey getStreamTemplateKey(BdfParameters bdfParameters, TransformationKey transformationKey, ValidExtension validExtension) {
        String userTemplateName = bdfParameters.getBdfUser().getPrefs().getStreamTemplateName(transformationKey, validExtension.toString());
        TemplateKey templateKey = null;
        if (userTemplateName != null) {
            try {
                templateKey = TemplateKey.parse(transformationKey, validExtension, userTemplateName);
            } catch (ParseException pe) {

            }
        }
        if (templateKey == null) {
            templateKey = resolveDefaultTemplate(bdfParameters, transformationKey, validExtension);
        }
        if (templateKey == null) {
            templateKey = TemplateKey.toDefault(transformationKey, validExtension);
        }
        return templateKey;
    }

    private static TemplateKey resolveDefaultTemplate(BdfParameters bdfParameters, TransformationKey transformationKey, ValidExtension validExtension) {
        AttributeResolver attributeResolver = new AttributeResolver(transformationKey, validExtension);
        TemplateKey result;
        Redacteur redacteur = bdfParameters.getBdfUser().getRedacteur();
        result = attributeResolver.resolve(redacteur.getAttributes());
        if (result != null) {
            return result;
        }
        result = attributeResolver.resolve(redacteur.getSphere().getMetadata().getAttributes());
        if (result != null) {
            return result;
        }
        result = attributeResolver.resolve(redacteur.getFichotheque().getFichothequeMetadata().getAttributes());
        if (result != null) {
            return result;
        }
        return result;
    }

    public static String getRootUrl(@Nullable BdfUser bdfUser) {
        if (bdfUser != null) {
            String sessionUrl = (String) bdfUser.getParameterValue(BdfUserConstants.SESSION_ROOTURL);
            if (sessionUrl != null) {
                return sessionUrl;
            }
        }
        return "";
    }

    public static boolean isWithJavascript(@Nullable BdfUser bdfUser) {
        if (bdfUser != null) {
            Boolean bool = (Boolean) bdfUser.getParameterValue(BdfUserConstants.HTML_WITHJAVASCRIPT);
            if (bool != null) {
                return bool;
            }
        }
        return false;
    }

    public static TypoOptions getTypoOptions(@Nullable BdfUser bdfUser) {
        if (bdfUser != null) {
            TypoOptions typoOptions = (TypoOptions) bdfUser.getParameterValue(BdfUserConstants.FORM_TYPOOPTIONS);
            if (typoOptions != null) {
                return typoOptions;
            }
        }
        return TypoOptions.getTypoOptions(Locale.FRENCH);
    }

    public static SheetWriter getSupplementarySheetWriter(BdfParameters bdfParameters) {
        if (!bdfParameters.getBdfUser().getPrefs().getBoolean(BdfUserSpace.TABLEEXPORT_STATUSSHEET_KEY)) {
            return null;
        }
        return new StatusSheetWriter(bdfParameters);
    }

    public static boolean isValidStoreKey(String key) {
        Matcher matcher = STORE_KEY_PATTERN.matcher(key);
        return matcher.matches();
    }

    public static boolean isValidStoreName(String name) {
        Matcher matcher = STORE_NAME_PATTERN.matcher(name);
        return matcher.matches();
    }

    public static String getCurrentSortType(BdfServer bdfServer, BdfUser bdfUser) {
        String storedValue = bdfServer.getStoredValue(bdfUser, "selection", "sort");
        if (storedValue == null) {
            return SortConstants.ID_ASC;
        }
        try {
            return SortConstants.checkSortType(storedValue);
        } catch (IllegalArgumentException iae) {
            return SortConstants.ID_ASC;
        }
    }


    private static class AttributeResolver {

        private final TransformationKey transformationKey;
        private final ValidExtension validExtension;
        private final AttributeKey attributeKey;

        private AttributeResolver(TransformationKey transformationKey, ValidExtension validExtension) {
            this.transformationKey = transformationKey;
            this.validExtension = validExtension;
            this.attributeKey = TransformationSpace.toDefaultTemplateAttributeKey(transformationKey, validExtension);
        }

        private TemplateKey resolve(Attributes attributes) {
            Attribute attribute = attributes.getAttribute(attributeKey);
            if (attribute == null) {
                return null;
            }
            try {
                return TemplateKey.parse(transformationKey, validExtension, attribute.getFirstValue());
            } catch (ParseException pe) {
                return null;
            }
        }

    }

}
