package be.iminds.ilabt.jfed.highlevel.jobs;

import be.iminds.ilabt.jfed.experiment.Experiment;
import be.iminds.ilabt.jfed.experiment.ExperimentPart;
import be.iminds.ilabt.jfed.highlevel.controller.TaskThread;
import be.iminds.ilabt.jfed.highlevel.jobs.parts.ExperimentPartControllerManager;
import be.iminds.ilabt.jfed.highlevel.jobs.states.JobStateFactory;
import be.iminds.ilabt.jfed.highlevel.model.SfaModel;
import be.iminds.ilabt.jfed.highlevel.model.Sliver;
import be.iminds.ilabt.jfed.highlevel.tasks.HighLevelTaskFactory;
import be.iminds.ilabt.jfed.highlevel.util.AggregateManagerWrapperFactory;
import be.iminds.ilabt.jfed.lowlevel.GeniUserProvider;
import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
import be.iminds.ilabt.jfed.lowlevel.api.user_spec.UserSpec;
import be.iminds.ilabt.jfed.lowlevel.authority.AuthorityFinder;

import be.iminds.ilabt.jfed.fedmon.webapi.service.json.*;
import be.iminds.ilabt.jfed.preferences.JFedPreferences;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXRspecLink;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXRspecNode;
import be.iminds.ilabt.jfed.util.GeniUrn;

import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.time.Instant;
import java.util.Collection;
import java.util.List;

@Singleton
public final class JobFactory {
    private final Provider<JFedPreferences> jFedPreferences;
    private final Provider<HighLevelTaskFactory> hltfProvider;
    private final Provider<TaskThread> ttProvider;
    private final Provider<AuthorityFinder> authorityFinderProvider;
    private final Provider<TestbedInfoSource> testbedInfoSourceProvider;
    private final Provider<AggregateManagerWrapperFactory> aggregateManagerWrapperFactoryProvider;
    private final Provider<GeniUserProvider> geniUserProviderProvider;
    private final Provider<SfaModel> sfaModelProvider;
    private final Provider<JobStateFactory> jobStateFactoryProvider;
    private final Provider<ExperimentPartControllerManager> epcManagerProvider;


    @Inject
    public JobFactory(Provider<HighLevelTaskFactory> hltfProvider,
                      Provider<JFedPreferences> jFedPreferences,
                      Provider<TaskThread> ttProvider,
                      Provider<AuthorityFinder> authorityFinderProvider,
                      Provider<TestbedInfoSource> testbedInfoSourceProvider,
                      Provider<AggregateManagerWrapperFactory> aggregateManagerWrapperFactoryProvider,
                      Provider<GeniUserProvider> geniUserProviderProvider,
                      Provider<SfaModel> sfaModelProvider,
                      Provider<JobStateFactory> jobStateFactoryProvider,
                      Provider<ExperimentPartControllerManager> epcManagerProvider) {
        this.hltfProvider = hltfProvider;
        this.jFedPreferences = jFedPreferences;
        this.ttProvider = ttProvider;
        this.authorityFinderProvider = authorityFinderProvider;
        this.testbedInfoSourceProvider = testbedInfoSourceProvider;
        this.aggregateManagerWrapperFactoryProvider = aggregateManagerWrapperFactoryProvider;
        this.geniUserProviderProvider = geniUserProviderProvider;
        this.sfaModelProvider = sfaModelProvider;
        this.jobStateFactoryProvider = jobStateFactoryProvider;
        this.epcManagerProvider = epcManagerProvider;
    }

//    public StartExperimentJob createAllocateExperimentJob(Experiment experiment) {
//        return new StartExperimentJob(experiment,
//                hltfProvider.get(), ttProvider.get(), authorityFinderProvider.get(),
//                aggregateManagerWrapperFactoryProvider.get(), geniUserProviderProvider.get(), sfaModelProvider.get(), jobStateFactoryProvider.get());
//    }

    public RestoreExperimentJob createRestoreExperimentJob(Experiment experiment) {
        return new RestoreExperimentJob(experiment, jFedPreferences.get(), hltfProvider.get(), ttProvider.get(), authorityFinderProvider.get(), jobStateFactoryProvider.get(), epcManagerProvider.get());
    }

    public UpdateExperimentJob createUpdateExperimentJob(Experiment experiment) {
        return new UpdateExperimentJob(experiment, hltfProvider.get(), ttProvider.get(), epcManagerProvider.get());
    }

    public StopExperimentJob createStopExperimentJob(Experiment experiment) {
        return new StopExperimentJob(experiment, hltfProvider.get(), ttProvider.get(), epcManagerProvider.get());
    }

    public StopExperimentJob createStopExperimentJob(Experiment experiment, Collection<ExperimentPart> experimentParts) {
        return new StopExperimentJob(experiment, experimentParts, hltfProvider.get(), ttProvider.get(), epcManagerProvider.get());
    }

    public ShareSliceJob createShareSliceJob(Experiment experiment, Collection<GeniUrn> usersToShareWith, boolean registerSshKeys) {
        return new ShareSliceJob(experiment, usersToShareWith, registerSshKeys, hltfProvider.get(), ttProvider.get(), jobStateFactoryProvider.get());
    }

    public EditSshKeysJob createEditSshKeysJob(Experiment experiment, List<UserSpec> userspec) {
        return new EditSshKeysJob(experiment, userspec, hltfProvider.get(), ttProvider.get(), jobStateFactoryProvider.get());
    }

    public ReloadOSJob createReloadOSJob(Experiment experiment, Sliver sliver) {
        return new ReloadOSJob(experiment, sliver, hltfProvider.get(), ttProvider.get(), jobStateFactoryProvider.get());
    }

    public CreateDiskImageJob createCreateDiskImageJob(Experiment experiment, FXRspecNode node, String imageName, boolean global, boolean updatePrepare) {
        return new CreateDiskImageJob(experiment, node, imageName, global, updatePrepare, hltfProvider.get(), ttProvider.get(), jobStateFactoryProvider.get());
    }

    public RegisterExperimentJob createRegisterExperimentJob(Experiment experiment) {
        return new RegisterExperimentJob(experiment, hltfProvider.get(), ttProvider.get());
    }

    public RebootJob createRebootJob(Experiment experiment, Sliver sliver) {
        return new RebootJob(experiment, sliver, hltfProvider.get(), ttProvider.get(), jobStateFactoryProvider.get());
    }

    public RebootJob createRebootJob(ExperimentPart experimentPart) {
        return new RebootJob(experimentPart, hltfProvider.get(), ttProvider.get(), jobStateFactoryProvider.get());
    }

    public OpenConsoleJob createOpenConsoleJob(Experiment experiment, Sliver sliver) {
        return new OpenConsoleJob(experiment, sliver, hltfProvider.get(), ttProvider.get());
    }


    public ShareLanJob createShareLanJob(Experiment experiment, FXRspecLink link, String sharedLanName) {
        return new ShareLanJob(experiment, link, sharedLanName, true /* share */, hltfProvider.get(), ttProvider.get(), authorityFinderProvider.get());
    }

    public ShareLanJob createUnshareLanJob(Experiment experiment, FXRspecLink link, String sharedLanName) {
        return new ShareLanJob(experiment, link, sharedLanName, false /* unshare */, hltfProvider.get(), ttProvider.get(), authorityFinderProvider.get());
    }

    public FetchSliceMemberSshKeysJob createFetchSliceMemberSshKeysJob(Experiment experiment) {
        return new FetchSliceMemberSshKeysJob(experiment, hltfProvider.get(), ttProvider.get());
    }

    public RenewJob createRenewJob(Experiment experiment, Instant newExpirationTime) {
        return new RenewJob(experiment, newExpirationTime, hltfProvider.get(), ttProvider.get(), epcManagerProvider.get());
    }

    public RenewJob createRenewJob(Experiment experiment, Instant newExpirationTime, Collection<ExperimentPart> experimentParts) {
        return new RenewJob(experiment, newExpirationTime, experimentParts, hltfProvider.get(), ttProvider.get(), epcManagerProvider.get());
    }


    public AllocateExperimentJob createAllocateExperimentJob(@Nonnull  Experiment experiment, @Nonnull  Server scsServer) {
       return new AllocateExperimentJob(experiment, scsServer, hltfProvider.get(), ttProvider.get(),
               jobStateFactoryProvider.get(),  testbedInfoSourceProvider.get(),
               authorityFinderProvider.get(), aggregateManagerWrapperFactoryProvider.get(), epcManagerProvider.get());
    }

    public ProvisionExperimentJob createProvisionExperimentJob(@Nonnull  Experiment experiment, boolean noWaitUntilReady) {
       return new ProvisionExperimentJob(experiment, hltfProvider.get(), ttProvider.get(),
               jobStateFactoryProvider.get(), aggregateManagerWrapperFactoryProvider.get(), epcManagerProvider.get(), noWaitUntilReady);
    }
}
