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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.fichotheque.FichothequeConstants;
import net.fichotheque.sphere.Redacteur;
import net.mapeadores.util.models.EmailCore;
import net.mapeadores.util.text.StringUtils;


/**
 *
 * @author Vincent Calame
 */
public class RedacteurSynthesis {

    public final static String A_ADMIN_LEVEL = "A";
    public final static String B_USER_LEVEL = "B";
    public final static String C_READONLY_LEVEL = "C";
    public final static String D_INACTIVE_LEVEL = "D";
    private final String login;
    private final Map<String, FichothequeStatus> statusMap = new HashMap<String, FichothequeStatus>();
    private final Map<String, Occurrence> nameOccurrenceMap = new HashMap<String, Occurrence>();
    private final Map<String, Occurrence> emailOccurrenceMap = new HashMap<String, Occurrence>();
    private Occurrence maxNameOccurrence = null;
    private Occurrence maxEmailOccurrence = null;

    public RedacteurSynthesis(String login) {
        this.login = login;
    }

    public String getLogin() {
        return login;
    }

    public String getCompleteName() {
        if (maxNameOccurrence != null) {
            return maxNameOccurrence.text;
        } else {
            return "";
        }
    }

    public String getEmail() {
        if (maxEmailOccurrence != null) {
            return maxEmailOccurrence.text;
        } else {
            return "";
        }
    }

    public List<String> getOtherNameList() {
        if (nameOccurrenceMap.size() < 2) {
            return StringUtils.EMPTY_STRINGLIST;
        }
        List<String> result = new ArrayList<String>();
        for (Occurrence nameOccurrence : nameOccurrenceMap.values()) {
            if (!nameOccurrence.equals(maxNameOccurrence)) {
                result.add(nameOccurrence.text);
            }

        }
        return result;
    }

    public List<String> getOtherEmailList() {
        if (emailOccurrenceMap.size() < 2) {
            return StringUtils.EMPTY_STRINGLIST;
        }
        List<String> result = new ArrayList<String>();
        for (Occurrence emailOccurrence : emailOccurrenceMap.values()) {
            if (!emailOccurrence.equals(maxEmailOccurrence)) {
                result.add(emailOccurrence.text);
            }

        }
        return result;
    }

    public void addRedacteur(Redacteur redacteur, String fichothequeName, boolean admin) {
        String level;
        if (admin) {
            level = A_ADMIN_LEVEL;
        } else {
            switch (redacteur.getStatus()) {
                case FichothequeConstants.INACTIVE_STATUS:
                    level = D_INACTIVE_LEVEL;
                    break;
                case FichothequeConstants.READONLY_STATUS:
                    level = C_READONLY_LEVEL;
                    break;
                default:
                    level = B_USER_LEVEL;
            }
        }
        Occurrence nameOccurrence = getNameOccurrence(redacteur, fichothequeName);
        Occurrence emailOccurrence = getEmailOccurrence(redacteur, fichothequeName);
        FichothequeStatus fichothequeStatus = new FichothequeStatus(fichothequeName, level, nameOccurrence, emailOccurrence);
        statusMap.put(fichothequeName, fichothequeStatus);
    }

    public FichothequeStatus getFichothequeStatus(String fichothequeName) {
        FichothequeStatus fichothequeStatus = statusMap.get(fichothequeName);
        if (fichothequeStatus == null) {
            return null;
        }
        return fichothequeStatus;
    }

    private Occurrence getNameOccurrence(Redacteur redacteur, String fichothequeName) {
        String completeName = redacteur.getPersonCore().toStandardStyle();
        Occurrence nameOccurrence = nameOccurrenceMap.get(completeName);
        if (nameOccurrence == null) {
            nameOccurrence = new Occurrence(completeName);
            nameOccurrenceMap.put(completeName, nameOccurrence);
        }
        nameOccurrence.add(fichothequeName);
        if (maxNameOccurrence == null) {
            maxNameOccurrence = nameOccurrence;
        } else if (nameOccurrence.size() > maxNameOccurrence.size()) {
            maxNameOccurrence = nameOccurrence;
        }
        return nameOccurrence;
    }

    private Occurrence getEmailOccurrence(Redacteur redacteur, String fichothequeName) {
        EmailCore emailCore = redacteur.getEmailCore();
        String completeEmail;
        if (emailCore != null) {
            completeEmail = emailCore.getAddrSpec();
        } else {
            completeEmail = "";
        }
        Occurrence emailOccurrence = emailOccurrenceMap.get(completeEmail);
        if (emailOccurrence == null) {
            emailOccurrence = new Occurrence(completeEmail);
            emailOccurrenceMap.put(completeEmail, emailOccurrence);
        }
        emailOccurrence.add(fichothequeName);
        if (maxEmailOccurrence == null) {
            maxEmailOccurrence = emailOccurrence;
        } else if (emailOccurrence.size() > maxEmailOccurrence.size()) {
            maxEmailOccurrence = emailOccurrence;
        }
        return emailOccurrence;
    }


    public class FichothequeStatus {

        private final String fichothequeName;
        private final String level;
        private final Occurrence nameOccurrence;
        private final Occurrence emailOccurrence;

        private FichothequeStatus(String fichothequeName, String level, Occurrence nameOccurrence, Occurrence emailOccurrence) {
            this.fichothequeName = fichothequeName;
            this.level = level;
            this.nameOccurrence = nameOccurrence;
            this.emailOccurrence = emailOccurrence;
        }

        public String getLevel() {
            return level;
        }

        public boolean hasSpecificName() {
            return !nameOccurrence.equals(maxNameOccurrence);
        }

        public String getSpecificName() {
            return nameOccurrence.text;
        }

        public boolean hasSpecificEmail() {
            return !emailOccurrence.equals(maxEmailOccurrence);
        }

        public String getSpecificEmail() {
            return emailOccurrence.text;
        }

    }


    private static class Occurrence {

        private final String text;
        private final Set<String> fichothequeNameSet = new HashSet<String>();

        private Occurrence(String name) {
            this.text = name;
        }

        private void add(String fichothequeName) {
            fichothequeNameSet.add(fichothequeName);
        }

        private int size() {
            return fichothequeNameSet.size();
        }


    }

}
