package com.doist.jobschedulercompat.scheduler.jobscheduler;

import com.doist.jobschedulercompat.JobInfo;
import com.doist.jobschedulercompat.job.JobStore;
import com.doist.jobschedulercompat.scheduler.Scheduler;

import android.annotation.TargetApi;
import android.app.job.JobScheduler;
import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.RestrictTo;

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@RestrictTo(RestrictTo.Scope.LIBRARY)
public class JobSchedulerScheduler extends Scheduler {
    public static final String TAG = "PlatformScheduler";

    private JobScheduler jobScheduler;

    public JobSchedulerScheduler(Context context, JobStore jobs) {
        super(context, jobs);
        jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    }

    @Override
    public int schedule(JobInfo job) {
        super.schedule(job);
        int result = jobScheduler.schedule(toPlatformJob(job));
        return result == JobScheduler.RESULT_SUCCESS ? RESULT_SUCCESS : RESULT_FAILURE;
    }

    @Override
    public void cancel(int jobId) {
        super.cancel(jobId);
        jobScheduler.cancel(jobId);
    }

    @Override
    public void cancelAll() {
        super.cancelAll();
        jobScheduler.cancelAll();
    }

    @NonNull
    @Override
    public String getTag() {
        return TAG;
    }

    private android.app.job.JobInfo toPlatformJob(JobInfo job) {
        if (job == null) {
            return null;
        }

        android.app.job.JobInfo.Builder builder =
                new android.app.job.JobInfo.Builder(job.getId(), job.getService())
                        .setExtras(job.getExtras().toPersistableBundle())
                        .setRequiresCharging(job.isRequireCharging())
                        .setPersisted(job.isPersisted());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            builder.setRequiredNetworkType(job.getNetworkType());
            if (job.isRequireDeviceIdle()) {
                builder.setRequiresDeviceIdle(true);
            } else {
                builder.setBackoffCriteria(job.getInitialBackoffMillis(), job.getBackoffPolicy());
            }
        } else {
            int networkType = job.getNetworkType();
            networkType = networkType != JobInfo.NETWORK_TYPE_NOT_ROAMING ? networkType : JobInfo.NETWORK_TYPE_ANY;
            builder.setRequiredNetworkType(networkType)
                   .setBackoffCriteria(job.getInitialBackoffMillis(), job.getBackoffPolicy());
        }

        if (job.isPeriodic()) {
            builder.setPeriodic(job.getIntervalMillis());
        } else {
            builder.setMinimumLatency(job.getMinLatencyMillis())
                   .setOverrideDeadline(job.getMaxExecutionDelayMillis());
        }

        return builder.build();
    }
}

@@ -429,16 +429,55 @@
 ictTo;%0A%0A
+import java.util.concurrent.TimeUnit;%0A%0A
 @TargetA
@@ -2066,227 +2066,65 @@
     
-if (job.isRequireDeviceIdle()) %7B%0A                builder.setRequiresDeviceIdle(true);%0A            %7D else %7B%0A                builder.setBackoffCriteria(job.getInitialBackoffMillis(), job.getBackoffPolicy());%0A            %7D
+builder.setRequiresDeviceIdle(job.isRequireDeviceIdle());
 %0A   
@@ -2201,16 +2201,20 @@
         
+if (
 networkT
@@ -2222,22 +2222,8 @@
 pe =
- networkType !
 = Jo
@@ -2252,18 +2252,35 @@
 _ROAMING
+) %7B%0A              
  
-?
  network
@@ -2284,17 +2284,17 @@
 orkType 
-:
+=
  JobInfo
@@ -2312,16 +2312,30 @@
 PE_ANY;%0A
+            %7D%0A
         
@@ -2381,16 +2381,18 @@
 orkType)
+;%0A
 %0A       
@@ -2392,31 +2392,582 @@
             
-       
+// Idle constraint is unavailable before N, which will crash if there are no other constraints.%0A            // Set a small latency to prevent this on non-periodic jobs (periodic jobs are inherently constrained).%0A            if (job.isRequireDeviceIdle() && !job.isPeriodic()) %7B%0A                builder.setMinimumLatency(TimeUnit.MINUTES.toMillis(1));%0A            %7D%0A        %7D%0A%0A        if (job.getBackoffPolicy() != JobInfo.DEFAULT_BACKOFF_POLICY%0A                %7C%7C job.getInitialBackoffMillis() != JobInfo.DEFAULT_INITIAL_BACKOFF_MILLIS) %7B%0A            builder
 .setBackoffC
@@ -3140,32 +3140,80 @@
        %7D else %7B%0A
+            if (job.hasEarlyConstraint()) %7B%0A    
             buil
@@ -3260,16 +3260,17 @@
 illis())
+;
 %0A       
@@ -3264,32 +3264,36 @@
 s());%0A          
+  %7D%0A
          .setOve
@@ -3281,24 +3281,81 @@
  %7D%0A         
+   if (job.hasLateConstraint()) %7B%0A                builder
 .setOverride
@@ -3390,32 +3390,46 @@
 DelayMillis());%0A
+            %7D%0A
         %7D%0A%0A     

Fix handling of idle constraint between L and N