// Path: src/it/reyboz/bustorino/backend/Fetcher.java
// public interface Fetcher {
//     /**
//      * Status codes.<br>
//      *<br>
//      * OK: got a response, parsed correctly, obtained some data<br>
//      * CLIENT_OFFLINE: can't connect to the internet<br>
//      * SERVER_ERROR: the server replied anything other than HTTP 200, basically<br>
//      *              for 404 special constant (see @FiveTAPIFetcher)
//      * PARSER_ERROR: the server replied something that can't be parsed, probably it's not the data we're looking for (e.g. "PHP: Fatal Error")<br>
//      * EMPTY_RESULT_SET: the response is valid and indicates there are no stops\routes\"passaggi"\results for your query<br>
//      * NOT_FOUND: response is valid, no parsing errors, but the desired stops/routes wasn't found
//      * QUERY_TOO_SHORT: input more characters and retry.
//      */
//     enum Result {
//         OK, CLIENT_OFFLINE, SERVER_ERROR, SETUP_ERROR,PARSER_ERROR, EMPTY_RESULT_SET, QUERY_TOO_SHORT, SERVER_ERROR_404,
//         CONNECTION_ERROR, NOT_FOUND
//     }
// }
// 
// Path: src/it/reyboz/bustorino/backend/Notifications.java
// public class Notifications {
//     public static final String DEFAULT_CHANNEL_ID ="Default";
// 
//     public static void createDefaultNotificationChannel(Context context) {
//         // Create the NotificationChannel, but only on API 26+ because
//         // the NotificationChannel class is new and not in the support library
//         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//             CharSequence name = context.getString(R.string.default_notification_channel);
//             String description = context.getString(R.string.default_notification_channel_description);
//             int importance = NotificationManager.IMPORTANCE_DEFAULT;
//             NotificationChannel channel = new NotificationChannel(DEFAULT_CHANNEL_ID, name, importance);
//             channel.setDescription(description);
//             // Register the channel with the system; you can't change the importance
//             // or other notification behaviors after this
//             NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
//             notificationManager.createNotificationChannel(channel);
//         }
//     }
// 
//     /**
//      * Register a notification channel on Android Oreo and above
//      * @param con a Context
//      * @param name channel name
//      * @param description channel description
//      * @param importance channel importance (from NotificationManager)
//      * @param ID channel ID
//      */
//     public static void createNotificationChannel(Context con, String name, String description, int importance, String ID){
//         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//             NotificationChannel channel = new NotificationChannel(ID, name, importance);
//             channel.setDescription(description);
//             // Register the channel with the system; you can't change the importance
//             // or other notification behaviors after this
//             NotificationManager notificationManager = con.getSystemService(NotificationManager.class);
//             notificationManager.createNotificationChannel(channel);
//         }
//     }
// }


import java.util.concurrent.atomic.AtomicReference;
import static android.content.Context.MODE_PRIVATE;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.work.*;
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.Fetcher;
import it.reyboz.bustorino.backend.Notifications;
import java.util.concurrent.TimeUnit;
        final int new_DB_version = DatabaseUpdate.getNewVersion();

        final boolean isUpdateCompulsory = getInputData().getBoolean(FORCED_UPDATE,false);

        final long lastDBUpdateTime = shPr.getLong(DatabaseUpdate.DB_LAST_UPDATE_KEY, 0);
        long currentTime = System.currentTimeMillis()/1000;

        final int notificationID = showNotification();
        Log.d(DEBUG_TAG, "Have previous version: "+current_DB_version +" and new version "+new_DB_version);
        Log.d(DEBUG_TAG, "Update compulsory: "+isUpdateCompulsory);
        /*
        SKIP CHECK (Reason: The Old API might fail at any moment)
        if (new_DB_version < 0){
            //there has been an error
            final Data out = new Data.Builder().putInt(ERROR_REASON_KEY, ERROR_FETCHING_VERSION)
                    .putInt(ERROR_CODE_KEY,new_DB_version).build();
            cancelNotification(notificationID);
            return ListenableWorker.Result.failure(out);
        }
         */

        //we got a good version
        if (!(current_DB_version < new_DB_version || currentTime > lastDBUpdateTime + UPDATE_MIN_DELAY )
                && !isUpdateCompulsory) {
            //don't need to update
            cancelNotification(notificationID);
            return ListenableWorker.Result.success(new Data.Builder().
                    putInt(SUCCESS_REASON_KEY, SUCCESS_NO_ACTION_NEEDED).build());
        }
        //start the real update
// Path: src/it/reyboz/bustorino/backend/Fetcher.java
// public interface Fetcher {
//     /**
//      * Status codes.<br>
//      *<br>
//      * OK: got a response, parsed correctly, obtained some data<br>
//      * CLIENT_OFFLINE: can't connect to the internet<br>
//      * SERVER_ERROR: the server replied anything other than HTTP 200, basically<br>
//      *              for 404 special constant (see @FiveTAPIFetcher)
//      * PARSER_ERROR: the server replied something that can't be parsed, probably it's not the data we're looking for (e.g. "PHP: Fatal Error")<br>
//      * EMPTY_RESULT_SET: the response is valid and indicates there are no stops\routes\"passaggi"\results for your query<br>
//      * NOT_FOUND: response is valid, no parsing errors, but the desired stops/routes wasn't found
//      * QUERY_TOO_SHORT: input more characters and retry.
//      */
//     enum Result {
//         OK, CLIENT_OFFLINE, SERVER_ERROR, SETUP_ERROR,PARSER_ERROR, EMPTY_RESULT_SET, QUERY_TOO_SHORT, SERVER_ERROR_404,
//         CONNECTION_ERROR, NOT_FOUND
//     }
// }
// 
// Path: src/it/reyboz/bustorino/backend/Notifications.java
// public class Notifications {
//     public static final String DEFAULT_CHANNEL_ID ="Default";
// 
//     public static void createDefaultNotificationChannel(Context context) {
//         // Create the NotificationChannel, but only on API 26+ because
//         // the NotificationChannel class is new and not in the support library
//         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//             CharSequence name = context.getString(R.string.default_notification_channel);
//             String description = context.getString(R.string.default_notification_channel_description);
//             int importance = NotificationManager.IMPORTANCE_DEFAULT;
//             NotificationChannel channel = new NotificationChannel(DEFAULT_CHANNEL_ID, name, importance);
//             channel.setDescription(description);
//             // Register the channel with the system; you can't change the importance
//             // or other notification behaviors after this
//             NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
//             notificationManager.createNotificationChannel(channel);
//         }
//     }
// 
//     /**
//      * Register a notification channel on Android Oreo and above
//      * @param con a Context
//      * @param name channel name
//      * @param description channel description
//      * @param importance channel importance (from NotificationManager)
//      * @param ID channel ID
//      */
//     public static void createNotificationChannel(Context con, String name, String description, int importance, String ID){
//         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//             NotificationChannel channel = new NotificationChannel(ID, name, importance);
//             channel.setDescription(description);
//             // Register the channel with the system; you can't change the importance
//             // or other notification behaviors after this
//             NotificationManager notificationManager = con.getSystemService(NotificationManager.class);
//             notificationManager.createNotificationChannel(channel);
//         }
//     }
// }


// Path: src/it/reyboz/bustorino/data/DBUpdateWorker.java
import java.util.concurrent.atomic.AtomicReference;
import static android.content.Context.MODE_PRIVATE;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.work.*;
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.Fetcher;
import it.reyboz.bustorino.backend.Notifications;
import java.util.concurrent.TimeUnit;

        final int new_DB_version = DatabaseUpdate.getNewVersion();

        final boolean isUpdateCompulsory = getInputData().getBoolean(FORCED_UPDATE,false);

        final long lastDBUpdateTime = shPr.getLong(DatabaseUpdate.DB_LAST_UPDATE_KEY, 0);
        long currentTime = System.currentTimeMillis()/1000;

        final int notificationID = showNotification();
        Log.d(DEBUG_TAG, "Have previous version: "+current_DB_version +" and new version "+new_DB_version);
        Log.d(DEBUG_TAG, "Update compulsory: "+isUpdateCompulsory);
        /*
        SKIP CHECK (Reason: The Old API might fail at any moment)
        if (new_DB_version < 0){
            //there has been an error
            final Data out = new Data.Builder().putInt(ERROR_REASON_KEY, ERROR_FETCHING_VERSION)
                    .putInt(ERROR_CODE_KEY,new_DB_version).build();
            cancelNotification(notificationID);
            return ListenableWorker.Result.failure(out);
        }
         */

        //we got a good version
        if (!(current_DB_version < new_DB_version || currentTime > lastDBUpdateTime + UPDATE_MIN_DELAY )
                && !isUpdateCompulsory) {
            //don't need to update
            cancelNotification(notificationID);
            return ListenableWorker.Result.success(new Data.Builder().
                    putInt(SUCCESS_REASON_KEY, SUCCESS_NO_ACTION_NEEDED).build());
        }
        //start the real update
        AtomicReference<Fetcher.Result> resultAtomicReference = new AtomicReference<>();