// Path: app/src/main/java/com/philliphsu/clock2/util/LocalBroadcastHelper.java
// public final class LocalBroadcastHelper {
// 
//     /** Sends a local broadcast using an intent with the action specified */
//     public static void sendBroadcast(Context context, String action) {
//         sendBroadcast(context, action, null);
//     }
// 
//     /** Sends a local broadcast using an intent with the action and the extras specified */
//     public static void sendBroadcast(Context context, String action, Bundle extras) {
//         Intent intent = new Intent(action);
//         if (extras != null) {
//             intent.putExtras(extras);
//         }
//         LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
//     }
// 
//     /** Registers a BroadcastReceiver that filters intents by the actions specified */
//     public static void registerReceiver(Context context, BroadcastReceiver receiver, String... actions) {
//         IntentFilter filter = new IntentFilter();
//         for (String action : actions)
//             filter.addAction(action);
//         LocalBroadcastManager.getInstance(context).registerReceiver(receiver, filter);
//     }
// 
//     public static void unregisterReceiver(Context context, BroadcastReceiver receiver) {
//         LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
//     }
// 
//     private LocalBroadcastHelper() {}
// }


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
import com.philliphsu.clock2.util.LocalBroadcastHelper;
/*
 * Copyright 2017 Phillip Hsu
 *
 * This file is part of ClockPlus.
 *
 * ClockPlus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ClockPlus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ClockPlus.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.philliphsu.clock2.data;



/**
 * Created by Phillip Hsu on 6/28/2016.
 *
 * Efficiently loads and holds a Cursor.
 */
public abstract class SQLiteCursorLoader<
        T extends ObjectWithId,
        C extends BaseItemCursor<T>>
    extends AsyncTaskLoader<C> {

    private static final String TAG = "SQLiteCursorLoader";

    private C mCursor;
    private OnContentChangeReceiver mOnContentChangeReceiver;

    public SQLiteCursorLoader(Context context) {
        super(context);
    }

    protected abstract C loadCursor();

    /**
     * @return the Intent action that will be registered to this Loader
     * for receiving broadcasts about underlying data changes to our
     * designated database table
     */
    protected abstract String getOnContentChangeAction();

    /* Runs on a worker thread */
    @Override
    public C loadInBackground() {
        C cursor = loadCursor();
        if (cursor != null) {
            // Ensure that the content window is filled
            // Ensure that the data is available in memory once it is
            // passed to the main thread
            cursor.getCount();
        }
        return cursor;
    }

    /* Runs on the UI thread */
    @Override
    public void deliverResult(C cursor) {
        if (isReset()) {
            // An async query came in while the loader is stopped
            if (cursor != null) {
                cursor.close();
            }
            return;
        }
        Cursor oldCursor = mCursor;
        mCursor = cursor;

        if (isStarted()) {
            super.deliverResult(cursor);
        }

        // Close the old cursor because it is no longer needed.
        // Because an existing cursor may be cached and redelivered, it is important
        // to make sure that the old cursor and the new cursor are not the
        // same before the old cursor is closed.
        if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
            oldCursor.close();
        }
    }

    // Refer to the docs if you wish to understand the rest of the API as used below.

    @Override
    protected void onStartLoading() {
        if (mCursor != null) {
            deliverResult(mCursor);
        }

        if (mOnContentChangeReceiver == null) {
            mOnContentChangeReceiver = new OnContentChangeReceiver();
// Path: app/src/main/java/com/philliphsu/clock2/util/LocalBroadcastHelper.java
// public final class LocalBroadcastHelper {
// 
//     /** Sends a local broadcast using an intent with the action specified */
//     public static void sendBroadcast(Context context, String action) {
//         sendBroadcast(context, action, null);
//     }
// 
//     /** Sends a local broadcast using an intent with the action and the extras specified */
//     public static void sendBroadcast(Context context, String action, Bundle extras) {
//         Intent intent = new Intent(action);
//         if (extras != null) {
//             intent.putExtras(extras);
//         }
//         LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
//     }
// 
//     /** Registers a BroadcastReceiver that filters intents by the actions specified */
//     public static void registerReceiver(Context context, BroadcastReceiver receiver, String... actions) {
//         IntentFilter filter = new IntentFilter();
//         for (String action : actions)
//             filter.addAction(action);
//         LocalBroadcastManager.getInstance(context).registerReceiver(receiver, filter);
//     }
// 
//     public static void unregisterReceiver(Context context, BroadcastReceiver receiver) {
//         LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
//     }
// 
//     private LocalBroadcastHelper() {}
// }


// Path: app/src/main/java/com/philliphsu/clock2/data/SQLiteCursorLoader.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
import com.philliphsu.clock2.util.LocalBroadcastHelper;

/*
 * Copyright 2017 Phillip Hsu
 *
 * This file is part of ClockPlus.
 *
 * ClockPlus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ClockPlus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ClockPlus.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.philliphsu.clock2.data;



/**
 * Created by Phillip Hsu on 6/28/2016.
 *
 * Efficiently loads and holds a Cursor.
 */
public abstract class SQLiteCursorLoader<
        T extends ObjectWithId,
        C extends BaseItemCursor<T>>
    extends AsyncTaskLoader<C> {

    private static final String TAG = "SQLiteCursorLoader";

    private C mCursor;
    private OnContentChangeReceiver mOnContentChangeReceiver;

    public SQLiteCursorLoader(Context context) {
        super(context);
    }

    protected abstract C loadCursor();

    /**
     * @return the Intent action that will be registered to this Loader
     * for receiving broadcasts about underlying data changes to our
     * designated database table
     */
    protected abstract String getOnContentChangeAction();

    /* Runs on a worker thread */
    @Override
    public C loadInBackground() {
        C cursor = loadCursor();
        if (cursor != null) {
            // Ensure that the content window is filled
            // Ensure that the data is available in memory once it is
            // passed to the main thread
            cursor.getCount();
        }
        return cursor;
    }

    /* Runs on the UI thread */
    @Override
    public void deliverResult(C cursor) {
        if (isReset()) {
            // An async query came in while the loader is stopped
            if (cursor != null) {
                cursor.close();
            }
            return;
        }
        Cursor oldCursor = mCursor;
        mCursor = cursor;

        if (isStarted()) {
            super.deliverResult(cursor);
        }

        // Close the old cursor because it is no longer needed.
        // Because an existing cursor may be cached and redelivered, it is important
        // to make sure that the old cursor and the new cursor are not the
        // same before the old cursor is closed.
        if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
            oldCursor.close();
        }
    }

    // Refer to the docs if you wish to understand the rest of the API as used below.

    @Override
    protected void onStartLoading() {
        if (mCursor != null) {
            deliverResult(mCursor);
        }

        if (mOnContentChangeReceiver == null) {
            mOnContentChangeReceiver = new OnContentChangeReceiver();
            LocalBroadcastHelper.registerReceiver(getContext(),