package org.jabref.logic.cleanup;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.xml.transform.TransformerException;

import org.jabref.logic.FilePreferences;
import org.jabref.logic.JabRefException;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.xmp.XmpUtilShared;
import org.jabref.logic.xmp.XmpUtilWriter;
import org.jabref.model.FieldChange;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.LinkedFile;
import org.jabref.model.entry.field.StandardField;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class XmpMetadataCleanup implements CleanupJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(XmpMetadataCleanup.class);

    private final BibDatabaseContext databaseContext;
    private final FilePreferences filePreferences;
    private final List<JabRefException> failures;

    public XmpMetadataCleanup(BibDatabaseContext databaseContext, FilePreferences filePreferences) {
        this.databaseContext = databaseContext;
        this.filePreferences = filePreferences;
        this.failures = new ArrayList<>();
    }

    @Override
    public List<FieldChange> cleanup(BibEntry entry) {
        List<LinkedFile> files = entry.getFiles();
        AtomicBoolean changed = new AtomicBoolean(false);
        for (LinkedFile file : files) {
            Optional<Path> filePath = file.findIn(databaseContext, filePreferences);
            filePath.ifPresent(path -> {
                // We need to check if a file has metadata to avoid performing the cleanup operation on all entries containing a linked file and to accurately report the FieldChange list.
                if (XmpUtilShared.hasMetadata(path)) {
                    try {
                        XmpUtilWriter.removeXmpMetadata(path);
                        changed.set(true);
                    } catch (IOException | TransformerException e) {
                        LOGGER.error("Problem removing XMP metadata from file {}", path, e);
                        failures.add(new JabRefException(Localization.lang("Problem removing XMP metadata from file: %0", path.toString()), e));
                    }
                }
            });
        }

        if (changed.get()) {
            // Since only metadata is removed, no field "changes" but we still return a list
            return List.of(new FieldChange(
                    entry,
                    StandardField.FILE,
                    // IntelliJ warning can be ignored since File field is always present if changed is true
                    entry.getField(StandardField.FILE).get(),
                    entry.getField(StandardField.FILE).get()
            ));
        }
        return List.of();
    }

    public List<JabRefException> getFailures() {
        return failures;
    }
}
