package io.github.lonamiwebs.stringlate.git;

import android.app.Activity;

import org.eclipse.jgit.lib.ProgressMonitor;

import io.github.lonamiwebs.stringlate.R;
import io.github.lonamiwebs.stringlate.interfaces.ProgressUpdateCallback;

public abstract class GitCloneProgressCallback
        implements ProgressUpdateCallback, ProgressMonitor {

    private Activity mActivity;
    private int mCurrentTask, mDone, mWork;

    private long mLastMs;

    private final static long DELAY_PER_UPDATE = 60; // 60ms

    protected GitCloneProgressCallback(Activity activity) {
        mActivity = activity;
    }

    @Override
    final public void beginTask(String title, int totalWork) {
        mCurrentTask++;
        mLastMs = 0;
        mDone = 0;
        mWork = totalWork;
    }

    @Override
    final public void update(int completed) {
        mDone += completed;

        // This method is called way so often, slow it down
        long time = System.currentTimeMillis();
        if (time - mLastMs >= DELAY_PER_UPDATE) {
            mLastMs = time;
            updateProgress();
        }
    }

    @Override
    final public void start(int totalTasks) { /* Total tasks is a liar */ }

    @Override
    final public void endTask() { }

    private void updateProgress() {
        final String title = mActivity.getString(R.string.cloning_repo);
        final String content = mActivity.getString(
                R.string.cloning_repo_progress, getProgress(mCurrentTask, mDone, mWork));

        // TODO This probably can be improved. Some handler to post the result?
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                onProgressUpdate(title, content);
            }
        });
    }

    private static float getProgress(int task, float done, float work) {
        // After timing cloning a large repository (F-Droid client) twice and averaging:
        // Task 1 → 2: 2ms     (0.003%)
        // Task 2 → 3: 125ms   (0.204%)
        // Task 3 → 4: 28010ms (45.74%)
        // Task 4 → 5: 33100ms (54.05%)
        if (work > 0 && task < 5) {
            return getTotalTime(task) + (done / work) * getTime(task);
        } else {
            return getTotalTime(task);
        }
    }

    private static float getTime(int task) {
        switch (task) {
            case 1: return 0.003f;
            case 2: return 0.204f;
            case 3: return 45.74f;
            case 4: return 54.52f;
            default: return 0.00f;
        }
    }

    private static float getTotalTime(int untilTask) {
        switch (untilTask) {
            case 1: return 0.000f;
            case 2: return 0.003f;
            case 3: return 0.207f;
            case 4: return 45.95f;
            default: return 1.00f;
        }
    }

    @Override
    final public boolean isCancelled() {
        return false;
    }
}

@@ -394,33 +394,49 @@
 nt m
-CurrentTask, mDone, mWork
+Done, mWork;%0A    private boolean mStarted
 ;%0A%0A 
@@ -523,16 +523,88 @@
 / 60ms%0A%0A
+    private final static String RECEIVING_TITLE = %22Receiving objects%22;%0A%0A
     prot
@@ -781,90 +781,114 @@
     
-mCurrentTask++;%0A        mLastMs = 0;%0A        mDone = 0;%0A        mWork = totalWork;
+if (title.equals(RECEIVING_TITLE)) %7B%0A            mWork = totalWork;%0A            mStarted = true;%0A        %7D
 %0A   
@@ -947,24 +947,68 @@
 ompleted) %7B%0A
+        if (!mStarted)%0A            return;%0A%0A
         mDon
@@ -1320,36 +1320,8 @@
 s) %7B
- /* Total tasks is a liar */
  %7D%0A%0A
@@ -1584,48 +1584,29 @@
 ss, 
-getProgress(mCurrentTask,
+100f *
  mDone
-,
+ /
  mWork)
-)
 ;%0A%0A 
@@ -1847,24 +1847,24 @@
           %7D%0A
+
         %7D);%0A
@@ -1874,1047 +1874,8 @@
  %7D%0A%0A
-    private static float getProgress(int task, float done, float work) %7B%0A        // After timing cloning a large repository (F-Droid client) twice and averaging:%0A        // Task 1 %E2%86%92 2: 2ms     (0.003%25)%0A        // Task 2 %E2%86%92 3: 125ms   (0.204%25)%0A        // Task 3 %E2%86%92 4: 28010ms (45.74%25)%0A        // Task 4 %E2%86%92 5: 33100ms (54.05%25)%0A        if (work %3E 0 && task %3C 5) %7B%0A            return getTotalTime(task) + (done / work) * getTime(task);%0A        %7D else %7B%0A            return getTotalTime(task);%0A        %7D%0A    %7D%0A%0A    private static float getTime(int task) %7B%0A        switch (task) %7B%0A            case 1: return 0.003f;%0A            case 2: return 0.204f;%0A            case 3: return 45.74f;%0A            case 4: return 54.52f;%0A            default: return 0.00f;%0A        %7D%0A    %7D%0A%0A    private static float getTotalTime(int untilTask) %7B%0A        switch (untilTask) %7B%0A            case 1: return 0.000f;%0A            case 2: return 0.003f;%0A            case 3: return 0.207f;%0A            case 4: return 45.95f;%0A            default: return 1.00f;%0A        %7D%0A    %7D%0A%0A
     

Improve git clone progress accuracy (#78)