package org.jabref.gui.mergeentries;

import java.util.Optional;
import java.util.Set;

import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.actions.ActionHelper;
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.gui.mergeentries.multiwaymerge.MultiMergeEntriesView;
import org.jabref.gui.preferences.GuiPreferences;
import org.jabref.gui.undo.CountingUndoManager;
import org.jabref.logic.importer.EntryBasedFetcher;
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.WebFetchers;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.TaskExecutor;
import org.jabref.model.entry.BibEntry;

public class UpdateWithBibliographicInformationByWebFetchers extends SimpleCommand {

    private final DialogService dialogService;
    private final GuiPreferences guiPreferences;
    private final StateManager stateManager;
    private final TaskExecutor taskExecutor;
    private final CountingUndoManager undoManager;

    public UpdateWithBibliographicInformationByWebFetchers(DialogService dialogService,
                                                           GuiPreferences preferences,
                                                           StateManager stateManager,
                                                           TaskExecutor taskExecutor,
                                                           CountingUndoManager undoManager) {
        this.dialogService = dialogService;
        this.guiPreferences = preferences;
        this.stateManager = stateManager;
        this.taskExecutor = taskExecutor;
        this.undoManager = undoManager;

        this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager));
    }

    @Override
    public void execute() {
        assert stateManager.getActiveDatabase().isPresent();

        BibEntry originalEntry = stateManager.getSelectedEntries().getFirst();

        MultiMergeEntriesView mergedEntriesView = new MultiMergeEntriesView(guiPreferences, taskExecutor);
        mergedEntriesView.addSource(Localization.lang("Original entry"), originalEntry);

        Set<EntryBasedFetcher> webFetchers = WebFetchers.getEntryBasedFetchers(
                guiPreferences.getImporterPreferences(),
                guiPreferences.getImportFormatPreferences(),
                guiPreferences.getFilePreferences(),
                stateManager.getActiveDatabase().get()
        );

        for (EntryBasedFetcher webFetcher : webFetchers) {
            mergedEntriesView.addSource(webFetcher.getName(), () -> {
                try {
                    return webFetcher.performSearch(originalEntry).stream().findFirst().orElse(null);
                } catch (FetcherException e) {
                    return null;
                }
            });
        }

        Optional<BibEntry> mergedEntry = dialogService.showCustomDialogAndWait(mergedEntriesView);
        new UpdateOriginalEntry(
                originalEntry,
                mergedEntry,
                dialogService,
                undoManager,
                Localization.lang("Merge entry with information"),
                Localization.lang("Updated entry with merged information"))
                .update();
    }
}
