package ctbrec.ui.settings;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import ctbrec.Config;
import ctbrec.recorder.postprocessing.CreateContactSheet;
import ctbrec.recorder.postprocessing.DeleteTooShort;
import ctbrec.recorder.postprocessing.Move;
import ctbrec.recorder.postprocessing.PostProcessor;
import ctbrec.recorder.postprocessing.Remux;
import ctbrec.recorder.postprocessing.Rename;
import ctbrec.recorder.postprocessing.Script;
import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.settings.api.Preferences;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.Region;

public class PostProcessingDialogFactory {

    static Map<Class<?>, Class<?>> ppToDialogMap = new HashMap<>();
    static {
        ppToDialogMap.put(Remux.class, RemuxerPaneFactory.class);
        ppToDialogMap.put(Script.class, ScriptPaneFactory.class);
        ppToDialogMap.put(Rename.class, RenamerPaneFactory.class);
        ppToDialogMap.put(Move.class, MoverPaneFactory.class);
        ppToDialogMap.put(DeleteTooShort.class, DeleteTooShortPaneFactory.class);
        ppToDialogMap.put(CreateContactSheet.class, CreateContactSheetPaneFactory.class);
    }

    private PostProcessingDialogFactory() {
    }

    public static void openNewDialog(PostProcessor pp, Config config, Scene scene, ObservableList<PostProcessor> stepList) {
        openDialog(pp, config, scene, stepList, true);
    }

    public static void openEditDialog(PostProcessor pp, Config config, Scene scene, ObservableList<PostProcessor> stepList) {
        openDialog(pp, config, scene, stepList, false);
    }

    private static void openDialog(PostProcessor pp, Config config, Scene scene, ObservableList<PostProcessor> stepList, boolean newEntry) {
        boolean ok;
        try {
            Optional<Preferences> preferences = createPreferences(pp);
            if(preferences.isPresent()) {
                Region view = preferences.get().getView(false);
                view.setMinWidth(600);
                ok = Dialogs.showCustomInput(scene, "Configure " + pp.getName(), view);
                if (ok) {
                    preferences.get().save();
                    if (newEntry) {
                        stepList.add(pp);
                    }
                }
            } else if (newEntry) {
                stepList.add(pp);
            }
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
                | InstantiationException | IOException e) {
            Dialogs.showError("New post-processing step", "Couldn't create dialog for " + pp.getName(), e);
        }
    }

    private static Optional<Preferences> createPreferences(PostProcessor pp) throws InstantiationException, IllegalAccessException, IllegalArgumentException,
    InvocationTargetException, NoSuchMethodException, SecurityException {
        Class<?> paneFactoryClass = ppToDialogMap.get(pp.getClass());
        if (paneFactoryClass != null) {
            AbstractPostProcessingPaneFactory factory = (AbstractPostProcessingPaneFactory) paneFactoryClass.getDeclaredConstructor().newInstance();
            return Optional.of(factory.createPostProcessorPane(pp));
        } else {
            return Optional.empty();
        }
    }
}
