package me.devsaki.hentoid.workers;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.work.Data;
import androidx.work.WorkerParameters;

import java.util.List;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import me.devsaki.hentoid.R;
import me.devsaki.hentoid.core.AppStartup;
import me.devsaki.hentoid.database.DatabaseMaintenance;
import me.devsaki.hentoid.notification.startup.StartupCompleteNotification;
import me.devsaki.hentoid.notification.startup.StartupProgressNotification;
import me.devsaki.hentoid.util.notification.Notification;
import timber.log.Timber;


/**
 * Worker responsible for running post-startup tasks
 */
public class StartupWorker extends BaseWorker {

    private Disposable launchDisposable = null;
    private List<Observable<Float>> launchTasks;


    public StartupWorker(
            @NonNull Context context,
            @NonNull WorkerParameters parameters) {
        super(context, parameters, R.id.startup_service);
    }

    @Override
    Notification getStartNotification() {
        return new StartupProgressNotification(0, 0);
    }

    @Override
    void onInterrupt() {
        // Nothing; won't happen
    }

    @Override
    void onClear() {
        launchTasks.clear();
    }

    @Override
    void getToWork(@NonNull Data input) {
        launchTasks = AppStartup.getPostLaunchTasks(getApplicationContext());
        launchTasks.addAll(DatabaseMaintenance.getPostLaunchCleanupTasks(getApplicationContext()));
        doRunTask(0,
                v -> notificationManager.notify(new StartupProgressNotification(Math.round(v * 100), 100)),
                v -> {
                },
                () -> notificationManager.notify(new StartupCompleteNotification()));
    }

    private void doRunTask(
            int taskIndex,
            @NonNull Consumer<Float> onMainProgress,
            @NonNull Consumer<Float> onSecondaryProgress,
            @NonNull Runnable onComplete
    ) {
        if (launchDisposable != null) launchDisposable.dispose();
        try {
            onMainProgress.accept(taskIndex * 1f / launchTasks.size());
        } catch (Exception e) {
            Timber.w(e);
        }
        // Continue executing launch tasks
        if (taskIndex < launchTasks.size()) {
            Timber.i("Post-launch task %s/%s", taskIndex + 1, launchTasks.size());
            launchDisposable = launchTasks.get(taskIndex)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(
                            onSecondaryProgress,
                            Timber::e,
                            () -> doRunTask(taskIndex + 1, onMainProgress, onSecondaryProgress, onComplete)
                    );
        } else {
            if (launchDisposable != null) launchDisposable.dispose();
            onComplete.run();
        }
    }
}

@@ -246,171 +246,30 @@
 vex.
-android.schedulers.AndroidSchedulers;%0Aimport io.reactivex.disposables.Disposable;%0Aimport io.reactivex.functions.Consumer;%0Aimport io.reactivex.schedulers.Schedulers
+disposables.Disposable
 ;%0Aim
@@ -1190,32 +1190,65 @@
     
-// Nothing; won't happen
+if (launchDisposable != null) launchDisposable.dispose();
 %0A   
@@ -1311,24 +1311,90 @@
 ks.clear();%0A
+        if (launchDisposable != null) launchDisposable.dispose();%0A
     %7D%0A%0A    @
@@ -1622,24 +1622,25 @@
 xt()));%0A
+%0A
         
 doRunTas
@@ -1635,128 +1635,57 @@
     
-doRunTask(0,%0A                v -%3E notificationManager.notify(new StartupProgressNotification(Math.round(v * 100), 100)),
+launchDisposable = Observable.concat(launchTasks)
 %0A   
@@ -1701,14 +1701,19 @@
     
-v -%3E %7B
+.subscribe(
 %0A   
@@ -1726,14 +1726,8 @@
     
-   %7D,%0A
     
@@ -1729,31 +1729,25 @@
             
-     ()
+v
  -%3E notifica
@@ -1780,903 +1780,57 @@
 rtup
-CompleteNotification()));%0A    %7D%0A%0A    private void doRunTask(%0A            int taskIndex,%0A            @NonNull Consumer%3CFloat%3E onMainProgress,%0A            @NonNull Consumer%3CFloat%3E onSecondaryProgress,%0A            @NonNull Runnable onComplete%0A    ) %7B%0A        if (launchDisposable != null) launchDisposable.dispose();%0A        try %7B%0A            onMainProgress.accept(taskIndex * 1f / launchTasks.size());%0A        %7D catch (Exception e) %7B%0A            Timber.w(e);%0A        %7D%0A        // Continue executing launch tasks%0A        if (taskIndex %3C launchTasks.size()) %7B%0A            Timber.i(%22Post-launch task %25s/%25s%22, taskIndex + 1, launchTasks.size());%0A            launchDisposable = launchTasks.get(taskIndex)%0A                    .subscribeOn(Schedulers.io())%0A                    .observeOn(AndroidSchedulers.mainThread())%0A                    .subscribe(%0A                            onSecondaryProgress,%0A    
+ProgressNotification(Math.round(v * 100), 100)),%0A
     
@@ -1888,201 +1888,75 @@
     
-    
 () -%3E 
-doRunTask(taskIndex + 1, onMainProgress, onSecondaryProgress, onComplete)%0A                    );%0A        %7D else %7B%0A            if (launchDisposable != null) launchDisposable.dispose();
+notificationManager.notify(new StartupCompleteNotification())
 %0A   
@@ -1968,35 +1968,14 @@
     
-onComplete.run();%0A        %7D
+    );
 %0A   

Fix startup worker not running all tasks