/* FichothequeLib_Tools - Copyright (c) 2019-2025 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.tools.exportation.table.inclusionresolvers;

import java.security.NoSuchAlgorithmException;
import net.fichotheque.Subset;
import net.fichotheque.exportation.table.Col;
import net.fichotheque.exportation.table.TableExportContext;
import net.fichotheque.exportation.table.TableInclusionDef;
import net.fichotheque.exportation.table.TableInclusionResolver;
import net.fichotheque.format.FormatSource;
import net.fichotheque.format.formatters.SourceFormatter;
import net.fichotheque.utils.TableDefUtils;
import net.fichotheque.utils.TableExportUtils;
import net.mapeadores.util.logging.LineMessageHandler;
import net.mapeadores.util.text.StringUtils;


/**
 *
 * @author Vincent Calame
 */
public class ChecksumInclusionResolver implements TableInclusionResolver {

    public final static String MD5_NAMESPACE = "md5";
    public final static String SHA1_NAMESPACE = "sha1";
    public final static String SHA2_NAMESPACE = "sha2";
    public final static ChecksumInclusionResolver MD5_INSTANCE = new ChecksumInclusionResolver(MD5_NAMESPACE, "MD5");
    public final static ChecksumInclusionResolver SHA1_INSTANCE = new ChecksumInclusionResolver(SHA1_NAMESPACE, "SHA-1");
    public final static ChecksumInclusionResolver SHA2_INSTANCE = new ChecksumInclusionResolver(SHA2_NAMESPACE, "SHA-256");
    private final String resolverNameSpace;
    private final InternalSourceFormatter sourceFormatter;

    private ChecksumInclusionResolver(String resolverNameSpace, String algorithm) {
        this.resolverNameSpace = resolverNameSpace;
        this.sourceFormatter = new InternalSourceFormatter(algorithm);
    }

    @Override
    public boolean test(TableInclusionDef tableInclusionDef, Subset subset, TableExportContext tableExportContext, int lineNumber, LineMessageHandler lineMessageHandler) {
        String nameSpace = tableInclusionDef.getNameSpace();
        if (!nameSpace.equals(resolverNameSpace)) {
            return false;
        }
        return true;
    }

    @Override
    public Col[] resolve(TableInclusionDef tableInclusionDef, Subset subset, TableExportContext tableExportContext) {
        String nameSpace = tableInclusionDef.getNameSpace();
        if (!nameSpace.equals(resolverNameSpace)) {
            return TableExportUtils.EMPTY_COLARRAY;
        }
        String localName = tableInclusionDef.getLocalName();
        if (localName.length() == 0) {
            localName = nameSpace;
        }
        Col[] colArray = new Col[1];
        colArray[0] = TableExportUtils.toCol(TableDefUtils.toColDef(localName, tableInclusionDef.getLabels()), sourceFormatter);
        return colArray;
    }


    private static class InternalSourceFormatter implements SourceFormatter {

        private final String algorithm;

        private InternalSourceFormatter(String algorithm) {
            this.algorithm = algorithm;
        }

        @Override
        public String formatSource(FormatSource formatSource) {
            StringBuilder buf = new StringBuilder();
            boolean next = false;
            for (String previous : formatSource.getHistory().getPreviousFormatList()) {
                if (next) {
                    buf.append(',');
                } else {
                    next = true;
                }
                if (previous != null) {
                    buf.append('"');
                    int length = previous.length();
                    for (int i = 0; i < length; i++) {
                        char carac = previous.charAt(i);
                        switch (carac) {
                            case '"':
                                buf.append("\\\"");
                                break;
                            case '\\':
                                buf.append("\\\\");
                                break;
                            default:
                                buf.append(carac);
                        }
                    }
                    buf.append('"');
                }
            }
            try {
                return StringUtils.digest(algorithm, buf.toString());
            } catch (NoSuchAlgorithmException e) {
                return "NoSuchAlgorithmException: " + algorithm;
            }
        }

    }

}
