/* BdfServer_Get - Copyright (c) 2015-2022 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.get.instructions;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.instruction.BdfInstruction;
import fr.exemole.bdfserver.api.instruction.BdfInstructionConstants;
import net.fichotheque.permission.PermissionSummary;
import fr.exemole.bdfserver.api.users.BdfUser;
import fr.exemole.bdfserver.tools.docstream.VersionDocStream;
import fr.exemole.bdfserver.tools.instruction.BdfInstructionUtils;
import fr.exemole.bdfserver.tools.roles.PermissionSummaryBuilder;
import java.text.ParseException;
import net.fichotheque.SubsetKey;
import net.fichotheque.addenda.Addenda;
import net.fichotheque.addenda.Document;
import net.fichotheque.addenda.Version;
import net.mapeadores.util.mimetype.MimeTypeResolver;
import net.mapeadores.util.mimetype.MimeTypeUtils;
import net.mapeadores.util.servlets.ResponseHandler;
import net.mapeadores.util.servlets.exceptions.ForbiddenException;
import net.mapeadores.util.servlets.handlers.DocStreamResponseHandler;


/**
 *
 * @author Vincent Calame
 */
public class DocumentsInstruction implements BdfInstruction {

    private final BdfServer bdfServer;
    private final Version version;

    private DocumentsInstruction(BdfServer bdfServer, Version version) {
        this.bdfServer = bdfServer;
        this.version = version;
    }

    @Override
    public short getBdfUserNeed() {
        return BdfInstructionConstants.MANDATORY_BDFUSER;
    }

    @Override
    public ResponseHandler runInstruction(BdfUser bdfUser) {
        PermissionSummary permissionSummary = PermissionSummaryBuilder.build(bdfServer, bdfUser);
        Addenda addenda = version.getDocument().getAddenda();
        if (!permissionSummary.hasAccess(addenda)) {
            throw new ForbiddenException();
        }
        MimeTypeResolver mimeTypeResolver = bdfServer.getMimeTypeResolver();
        String mimeType = MimeTypeUtils.getMimeType(mimeTypeResolver, version.getFileName());
        String charset = MimeTypeUtils.getDefaultCharset(mimeType);
        return new DocStreamResponseHandler(new VersionDocStream(version, mimeType, charset));
    }

    public static BdfInstruction build(BdfServer bdfServer, String filePath) {
        int idx1 = filePath.indexOf('/');
        BdfInstruction bdfInstruction;
        if (idx1 == -1) {
            bdfInstruction = buildFromId(bdfServer, filePath);
        } else {
            bdfInstruction = buildFromName(bdfServer, filePath.substring(0, idx1), filePath.substring(idx1 + 1));
        }
        if (bdfInstruction == null) {
            bdfInstruction = BdfInstructionUtils.NOTFOUND_BDFINSTRUCTION;
        }
        return bdfInstruction;
    }

    private static BdfInstruction buildFromName(BdfServer bdfServer, String addendaName, String documentName) {
        SubsetKey addendaKey;
        try {
            addendaKey = SubsetKey.parse(SubsetKey.CATEGORY_ADDENDA, addendaName);
        } catch (ParseException pe) {
            return null;
        }
        int idx3 = documentName.lastIndexOf('.');
        if (idx3 == -1) {
            return null;
        }
        String basename = documentName.substring(0, idx3);
        String extension = documentName.substring(idx3 + 1);
        Addenda addenda = (Addenda) bdfServer.getFichotheque().getSubset(addendaKey);
        if (addenda == null) {
            return null;
        }
        Document document = addenda.getDocumentByBasename(basename);
        if (document == null) {
            return null;
        }
        Version version = document.getVersionByExtension(extension);
        if (version == null) {
            return null;
        }
        return new DocumentsInstruction(bdfServer, version);
    }

    private static BdfInstruction buildFromId(BdfServer bdfServer, String documentName) {
        int idx2 = documentName.indexOf('-');
        if (idx2 == -1) {
            return null;
        }
        int idx3 = documentName.indexOf('.');
        if (idx3 == -1) {
            return null;
        }
        if (idx3 < idx2) {
            return null;
        }
        SubsetKey addendaKey;
        try {
            addendaKey = SubsetKey.parse(SubsetKey.CATEGORY_ADDENDA, documentName.substring(0, idx2));
        } catch (ParseException pe) {
            return null;
        }
        int documentid;
        try {
            documentid = Integer.parseInt(documentName.substring(idx2 + 1, idx3));
        } catch (NumberFormatException nfe) {
            return null;
        }
        String extension = documentName.substring(idx3 + 1);
        Addenda addenda = (Addenda) bdfServer.getFichotheque().getSubset(addendaKey);
        if (addenda == null) {
            return null;
        }
        Document document = addenda.getDocumentById(documentid);
        if (document == null) {
            return null;
        }
        Version version = document.getVersionByExtension(extension);
        if (version == null) {
            return null;
        }
        return new DocumentsInstruction(bdfServer, version);
    }

}
