package manparvesh.ideatrackerplus.database;

import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.design.widget.Snackbar;
import android.support.v4.util.Pair;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

import manparvesh.ideatrackerplus.ItemAdapter;
import manparvesh.ideatrackerplus.MainActivity;
import manparvesh.ideatrackerplus.R;
import manparvesh.ideatrackerplus.SearchListAdapter;

/**
 * This class takes care of the interaction with the database
 * where the ideas are stored.
 */
public class DatabaseHelper extends SQLiteOpenHelper {

    private static DatabaseHelper sInstance;

    // Store the list adapters to notify changes in the database
    private static ItemAdapter[] adapters = new ItemAdapter[4];

    // Needs to display the number of ideas at all time
    private static MainActivity mainActivity;

    // Keeps the ideas which have just been moved with "move all" to undo the action
    private static ArrayList<Pair<Integer, String>> movedIdeas;
    // Keep the idea last moved with "moveToTab" to undo the action
    private static Pair<Integer, Integer> lastMoved;
    private static int lastMovedOrderIndex;

    // If the database schema change, must increment the database version.
    public static final int DATABASE_VERSION = 2;
    public static final String DATABASE_NAME = "MyIdeas.db";

    //SQL COMMANDS
    private static final String TEXT_TYPE = " TEXT";
    private static final String INT_TYPE = " INT";
    private static final String BOOL_TYPE = " BOOLEAN";
    private static final String COMMA_SEP = ",";
    private static final String SQL_DELETE_ENTRIES =
            "DROP TABLE IF EXISTS " + DataEntry.TABLE_NAME;

    /**
     * This methods is used to get an instance of the class and ensure
     * uniqueness (singleton)
     *
     * @param context
     * @return the helper object
     */
    public static synchronized DatabaseHelper getInstance(Context context) {

        if (sInstance == null) {
            sInstance = new DatabaseHelper(context.getApplicationContext());
        }
        return sInstance;
    }


    // SET ADAPTERS

    public static void setAdapterAtTab(int tabNumber, ItemAdapter adapter) {
        if (1 <= tabNumber && tabNumber <= 3) {
            adapters[tabNumber] = adapter;
        }
    }

    private DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        mainActivity = MainActivity.getInstance();
    }

    /**
     * Nothing is created at first
     *
     * @param db
     */
    public void onCreate(SQLiteDatabase db) {
        //Do nothing
    }

    /**
     * Called when newer version of the database
     * so users don't their data
     *
     * @param db
     * @param oldVersion
     * @param newVersion
     */
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(SQL_DELETE_ENTRIES);
        onCreate(db);
    }

    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onUpgrade(db, oldVersion, newVersion);
    }

    /**
     * Notify the list adapters of the data changes
     */
    public static void notifyAllLists() {

        DatabaseHelper helper = DatabaseHelper.getInstance(mainActivity);

        //Notify all 3 tabs
        for (int tab = 1; tab <= 3; tab++) {
            if (adapters[tab] != null) adapters[tab].setItemList(helper.readIdeas(tab));
        }

        //Notify search tab
        SearchListAdapter.getInstance(mainActivity, false).notifyDataSetChanged();

    }


    //TABLE OPERATIONS

    /**
     * Creates a new table (project) in the database
     *
     * @param tableName
     */
    public void newTable(String tableName) {

        DataEntry.setTableName(tableName);
        String SQL_NEW_TABLE =
                "CREATE TABLE " + DataEntry.TABLE_NAME + " (" +
                        DataEntry._ID + " INTEGER PRIMARY KEY," +
                        DataEntry.COLUMN_NAME_ENTRY_ID + INT_TYPE + COMMA_SEP +
                        DataEntry.COLUMN_NAME_TEXT + TEXT_TYPE + COMMA_SEP +
                        DataEntry.COLUMN_NAME_NOTE + TEXT_TYPE + COMMA_SEP +
                        DataEntry.COLUMN_NAME_PRIORITY + INT_TYPE + COMMA_SEP +
                        DataEntry.COLUMN_NAME_DONE + BOOL_TYPE + COMMA_SEP +
                        DataEntry.COLUMN_NAME_LATER + BOOL_TYPE + COMMA_SEP +
                        DataEntry.COLUMN_NAME_TEMP + BOOL_TYPE +
                        " )";
        getWritableDatabase().execSQL(SQL_NEW_TABLE);
        notifyAllLists();
    }

    /**
     * Select another table (project)
     *
     * @param tableName
     */
    public void switchTable(String tableName) {
        DataEntry.setTableName(tableName);
        notifyAllLists();
    }

    /**
     * Rename the current table
     *
     * @param newName
     */
    public void renameTable(String newName) {
        getWritableDatabase().execSQL("ALTER TABLE " + DataEntry.TABLE_NAME + " RENAME TO " + "[" + newName + "]");
        DataEntry.setTableName(newName);
        notifyAllLists();
    }

    /**
     * Delete the current table
     */
    public void deleteTable() {
        String SQL_DELETE =
                "DROP TABLE IF EXISTS " + DataEntry.TABLE_NAME;
        getWritableDatabase().execSQL(SQL_DELETE);
    }


    //ENTRY OPERATIONS

    /**
     * Create an entry (idea) in the current table (project)
     *
     * @param text
     * @param note
     * @param priority range from 1 (high) to 3 (low)
     * @param later    if the idea should be in the "LATER" tab
     */
    public void newEntry(String text, String note, int priority, boolean later) {

        ContentValues values = new ContentValues();
        if (later) {
            values.put(DataEntry.COLUMN_NAME_ENTRY_ID, getLastOrderIndex(2) + 1); // The order index is set so the item is the last in the list
        } else {
            values.put(DataEntry.COLUMN_NAME_ENTRY_ID, getLastOrderIndex(1) + 1);
        }
        values.put(DataEntry.COLUMN_NAME_TEXT, text);
        values.put(DataEntry.COLUMN_NAME_NOTE, note);
        values.put(DataEntry.COLUMN_NAME_PRIORITY, priority);
        values.put(DataEntry.COLUMN_NAME_LATER, later);
        values.put(DataEntry.COLUMN_NAME_DONE, false);
        values.put(DataEntry.COLUMN_NAME_TEMP, false);

        getWritableDatabase().insert(
                DataEntry.TABLE_NAME,
                DataEntry.COLUMN_NAME_NULLABLE,
                values);
    }


    /**
     * Find an entry cursor with its id
     *
     * @param id
     * @return a Cursor object containing the idea's information
     */
    public Cursor getEntryById(int id) {
        SQLiteDatabase db = this.getReadableDatabase();
        return db.query(
                DataEntry.TABLE_NAME,  // The table to query
                null,                               // The columns to return
                "_id=?",                    // The columns for the WHERE clause
                new String[]{Integer.toString(id)},                  // The values for the WHERE clause
                null,                                     // don't group the rows
                null,                                     // don't filter by row groups
                null                                 // The sort order
        );
    }

    public String getTextById(int id) {
        Cursor cursor = null;
        try {
            cursor = getEntryById(id);
            if (cursor.moveToFirst()) {
                while (!cursor.isAfterLast()) {
                    return cursor.getString(cursor.getColumnIndex(DataEntry.COLUMN_NAME_TEXT));
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return "Nothing";
    }

    public String getNoteById(int id) {
        Cursor cursor = null;
        try {
            cursor = getEntryById(id);
            if (cursor.moveToFirst()) {
                while (!cursor.isAfterLast()) {
                    return cursor.getString(cursor.getColumnIndex(DataEntry.COLUMN_NAME_NOTE));
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return "Nothing";
    }

    public int getPriorityById(int id) {
        Cursor cursor = null;
        try {
            cursor = getEntryById(id);
            if (cursor.moveToFirst()) {
                while (!cursor.isAfterLast()) {
                    return cursor.getInt(cursor.getColumnIndex(DataEntry.COLUMN_NAME_PRIORITY));
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return 0;
    }

    public int getPriorityColorById(int id) {
        int priority = getPriorityById(id);

        switch (priority) {
            case 1:
                return R.color.priority1;

            case 2:
                return R.color.priority2;

            case 3:
                return R.color.priority3;
        }

        return R.color.white;
    }

    public int getOrderIndexById(int id) {
        Cursor cursor = null;
        try {
            cursor = getEntryById(id);
            if (cursor.moveToFirst()) {
                while (!cursor.isAfterLast()) {
                    return cursor.getInt(cursor.getColumnIndex(DataEntry.COLUMN_NAME_ENTRY_ID));
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return 0;
    }

    public int getTabById(int id) {

        Cursor cursor = null;
        try {
            cursor = getEntryById(id);
            if (cursor.moveToFirst()) {
                while (!cursor.isAfterLast()) {
                    boolean later = cursor.getInt(cursor.getColumnIndex(DataEntry.COLUMN_NAME_LATER)) > 0;
                    boolean done = cursor.getInt(cursor.getColumnIndex(DataEntry.COLUMN_NAME_DONE)) > 0;

                    if (done) {
                        return 3;
                    } else if (later) {
                        return 2;
                    }
                    return 1;
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return 1;
    }

    /**
     * Modify an entry's values
     *
     * @param id
     * @param new_text
     * @param new_note
     * @param new_priority
     * @param later
     */
    public void editEntry(int id, String new_text, String new_note, int new_priority, boolean later) {

        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DataEntry.COLUMN_NAME_TEXT, new_text);
        values.put(DataEntry.COLUMN_NAME_NOTE, new_note);
        values.put(DataEntry.COLUMN_NAME_PRIORITY, new_priority);
        if (later) {
            values.put(DataEntry.COLUMN_NAME_LATER, true);
            values.put(DataEntry.COLUMN_NAME_DONE, false);
        } else {
            values.put(DataEntry.COLUMN_NAME_LATER, false);
        }
        db.update(DataEntry.TABLE_NAME, values, "_id=" + id, null);
        notifyAllLists();
    }


    //MOVING ENTRIES

    public void deleteEntry(int id) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(DataEntry.TABLE_NAME, "_id=" + id, null);
    }

    /**
     * Mark entry for deletion (temp = 1) and show a snackbar
     * giving the option to undo the deletion, if the users does not
     * the idea is deleted.
     *
     * @param view
     * @param id
     */
    public void deleteEntryWithSnack(View view, final int id) {

        moveToTemp(id);

        Snackbar snackbar = Snackbar.make(view, R.string.idea_deleted, Snackbar.LENGTH_LONG)
                .setAction(R.string.undo, new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        recoverFromTemp(id);
                        notifyAllLists();
                        mainActivity.displayIdeasCount();
                    }
                }).setCallback(new Snackbar.Callback() {
                    @Override
                    public void onDismissed(Snackbar snackbar, int event) {
                        if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
                            //delete for real ideas in temp
                            deleteEntry(id);
                        }
                    }
                });
        snackbar.show();
    }

    public void moveToTemp(int id) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DataEntry.COLUMN_NAME_TEMP, true);
        db.update(DataEntry.TABLE_NAME, values, "_id=" + id, null);
    }

    public void recoverFromTemp(int id) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DataEntry.COLUMN_NAME_TEMP, false);
        db.update(DataEntry.TABLE_NAME, values, "_id=" + id, null);
    }

    public void moveAllToTemp(ArrayList<Pair<Integer, String>> ideas) {
        for (Pair<Integer, String> idea : ideas) {
            moveToTemp(idea.first);
        }
        notifyAllLists();
    }

    public void recoverAllFromTemp() {
        ArrayList<Integer> temp = readTempIdeas();
        for (int id : temp) {
            recoverFromTemp(id);
        }
        notifyAllLists();
    }

    public void deleteAllFromTemp() {
        ArrayList<Integer> temp = readTempIdeas();
        for (int id : temp) {
            deleteEntry(id);
        }
        notifyAllLists();
    }

    /**
     * Move an idea to another tab displaying a snackbar allowing to undo the action
     *
     * @param view a reference view to display to snackbar
     * @param from tab numer the idea comes from
     * @param to   tab number where to move the idea
     * @param id   unique id of the idea in database
     */
    public void moveToTabWithSnack(View view, int from, int to, int id) {

        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        Resources res = mainActivity.getResources();
        String destination = "";

        switch (to) {
            case 1: //NOW
                destination = res.getString(R.string.first_tab);
                values.put(DataEntry.COLUMN_NAME_ENTRY_ID, getLastOrderIndex(1) + 1);
                values.put(DataEntry.COLUMN_NAME_DONE, false);
                values.put(DataEntry.COLUMN_NAME_LATER, false);
                break;

            case 2: //LATER
                destination = res.getString(R.string.second_tab);
                values.put(DataEntry.COLUMN_NAME_ENTRY_ID, getLastOrderIndex(2) + 1);
                values.put(DataEntry.COLUMN_NAME_DONE, false);
                values.put(DataEntry.COLUMN_NAME_LATER, true);
                break;

            case 3: //DONE
                destination = res.getString(R.string.third_tab);
                values.put(DataEntry.COLUMN_NAME_ENTRY_ID, getLastOrderIndex(3) + 1);
                values.put(DataEntry.COLUMN_NAME_LATER, false);
                values.put(DataEntry.COLUMN_NAME_DONE, true);
                break;
        }

        //Keeps the idea info if action has to be undone
        lastMoved = new Pair<>(from, id);
        lastMovedOrderIndex = getOrderIndexById(id);

        db.update(DataEntry.TABLE_NAME, values, "_id=" + id, null);

        //Show snackbar allowing undo action
        Snackbar snackbar = Snackbar.make(view, res.getString(R.string.idea_moved_snack) + destination, Snackbar.LENGTH_LONG)
                .setAction(R.string.undo, new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        undoLastMove();
                        mainActivity.displayIdeasCount();
                    }
                });
        snackbar.show();
    }

    /**
     * Move an idea to another tab
     *
     * @param to
     * @param id
     * @param orderIndex
     */
    public void moveToTab(int to, int id, int orderIndex) {

        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        switch (to) {
            case 1: //NOW
                values.put(DataEntry.COLUMN_NAME_DONE, false);
                values.put(DataEntry.COLUMN_NAME_LATER, false);
                break;

            case 2: //LATER
                values.put(DataEntry.COLUMN_NAME_DONE, false);
                values.put(DataEntry.COLUMN_NAME_LATER, true);
                break;

            case 3: //DONE
                values.put(DataEntry.COLUMN_NAME_LATER, false);
                values.put(DataEntry.COLUMN_NAME_DONE, true);
                break;
        }
        values.put(DataEntry.COLUMN_NAME_ENTRY_ID, orderIndex);

        db.update(DataEntry.TABLE_NAME, values, "_id=" + id, null);
    }

    // Move back the last idea moved with moveToTab method
    private void undoLastMove() {
        moveToTab(lastMoved.first, lastMoved.second, lastMovedOrderIndex);
        notifyAllLists();
    }

    public void moveAllToTab(int tabNumber, ArrayList<Pair<Integer, String>> ideas) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        switch (tabNumber) {
            case 1: //NOW
                values.put(DataEntry.COLUMN_NAME_DONE, false);
                values.put(DataEntry.COLUMN_NAME_LATER, false);
                break;

            case 2: //LATER
                values.put(DataEntry.COLUMN_NAME_DONE, false);
                values.put(DataEntry.COLUMN_NAME_LATER, true);
                break;

            case 3: //DONE
                values.put(DataEntry.COLUMN_NAME_LATER, false);
                values.put(DataEntry.COLUMN_NAME_DONE, true);
                break;
        }

        for (Pair<Integer, String> idea : ideas) {
            db.update(DataEntry.TABLE_NAME, values, "_id=" + idea.first, null);
        }
        notifyAllLists();
    }

    /**
     * Move all ideas from a tab to another
     *
     * @param from
     * @param to
     */
    public boolean moveAllFromTo(String from, String to) {

        ArrayList<Pair<Integer, String>> ideas = new ArrayList<>();
        Context c = mainActivity.getApplicationContext();

        if (from.equals(c.getString(R.string.first_tab))) { //get all the ideas from NOW tab
            ideas = readIdeas(1);
        } else if (from.equals(c.getString(R.string.second_tab))) {//get all the ideas from LATER tab
            ideas = readIdeas(2);
        } else if (from.equals(c.getString(R.string.third_tab))) {//get all the ideas from DONE tab
            ideas = readIdeas(3);
        }


        if (ideas.size() == 0) return false; //nothing to move
        movedIdeas = ideas; //store the ideas for UNDO action


        if (to.equals(c.getString(R.string.first_tab))) {
            moveAllToTab(1, ideas);
        } else if (to.equals(c.getString(R.string.second_tab))) {
            moveAllToTab(2, ideas);
        } else if (to.equals(c.getString(R.string.third_tab))) {
            moveAllToTab(3, ideas);
        } else if (to.equals(c.getString(R.string.trash))) {
            moveAllToTemp(ideas);
        }
        return true;
    }


    public void clearDoneWithSnack(View v) {

        //put all done ideas in temps
        moveAllFromTo("Done", "Trash");

        Snackbar snackbar = Snackbar.make(v, R.string.done_cleared, Snackbar.LENGTH_LONG)
                .setAction(R.string.undo, new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        recoverAllFromTemp();
                    }
                }).setCallback(new Snackbar.Callback() {
                    @Override
                    public void onDismissed(Snackbar snackbar, int event) {
                        if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT || event == Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE) {
                            deleteAllFromTemp();
                        }
                    }
                });
        snackbar.show();
    }


    //READING OPERATIONS

    /**
     * Retrieve the ideas of the LATER or DONE tab with the desired priority
     *
     * @param tabNumber 1 for NOW/IDEAS, 2 for LATER, 3 for DONE
     * @return a list of the ideas paired with their id in the database
     */
    public ArrayList<Pair<Integer, String>> readIdeas(int tabNumber) {

        if (!DataEntry.TABLE_NAME.equals("[]")) {

            SQLiteDatabase db = this.getReadableDatabase();

            // Only the text and id will be read
            String[] projection = {DataEntry._ID, DataEntry.COLUMN_NAME_TEXT};

            // How you want the results sorted in the resulting Cursor
            String sortOrder = DataEntry.COLUMN_NAME_ENTRY_ID + " ASC";

            //Define the where condition
            String where = "";
            String[] values = {};
            switch (tabNumber) {
                case 1:
                    where = "later=? and done=? and temp=?";
                    values = new String[]{"0", "0", "0"};
                    break;

                case 2:
                    where = "later=? and temp=?";
                    values = new String[]{"1", "0"};
                    break;

                case 3:
                    where = "done=? and temp=?";
                    values = new String[]{"1", "0"};
                    break;
            }

            Cursor cursor = null;
            ArrayList<Pair<Integer, String>> ideas = new ArrayList<>();
            try {
                cursor = db.query(
                        DataEntry.TABLE_NAME,  // The table to query
                        projection,                               // The columns to return
                        where,                                   // The columns for the WHERE clause
                        values,                      // The values for the WHERE clause
                        null,                                     // don't group the rows
                        null,                                     // don't filter by row groups
                        sortOrder                                 // The sort order
                );


                Pair<Integer, String> pair;

                //Scan the ideas and return everything
                if (cursor.moveToFirst()) {

                    while (!cursor.isAfterLast()) {
                        String text = cursor.getString(cursor.getColumnIndex(DataEntry.COLUMN_NAME_TEXT));
                        int id = cursor.getInt(cursor.getColumnIndex(DataEntry._ID));
                        pair = new Pair<>(id, text);
                        ideas.add(pair);
                        cursor.moveToNext();
                    }
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
            return ideas;
        }

        return new ArrayList<>();
    }

    /**
     * Count the ideas in the different tabs for the current project (table)
     *
     * @param tabNumber 0 for NOW+LATER, 1 for Now/IDEAS, 2 for LATER, 3 for DONE
     * @return
     */
    public int getIdeasCount(int tabNumber) {

        int count = 0;
        Cursor cursor = null;
        try {
            switch (tabNumber) {
                case 0: //NOW+LATER
                    cursor = getReadableDatabase().rawQuery("select count(*) from " + DataEntry.TABLE_NAME + " where done=0 and temp=0", null);
                    break;

                case 1: //NOW/IDEAS
                    cursor = getReadableDatabase().rawQuery("select count(*) from " + DataEntry.TABLE_NAME + " where done=0 and temp=0 and later=0", null);
                    break;

                case 2: //LATER
                    cursor = getReadableDatabase().rawQuery("select count(*) from " + DataEntry.TABLE_NAME + " where done=0 and temp=0 and later=1", null);
                    break;

                case 3: //DONE
                    cursor = getReadableDatabase().rawQuery("select count(*) from " + DataEntry.TABLE_NAME + " where done=1 and temp=0", null);
                    break;
            }

            cursor.moveToFirst();
            count = cursor.getInt(0);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return count;
    }

    /**
     * Get the last (and bigger) order index of the given tab item list
     *
     * @param tabNumber
     * @return
     */
    public int getLastOrderIndex(int tabNumber) {

        int lastOrderIndex = -1;

        if (!DataEntry.TABLE_NAME.equals("[]")) {

            SQLiteDatabase db = this.getReadableDatabase();

            // Only the text and priority will be read
            String[] projection = {DataEntry.COLUMN_NAME_ENTRY_ID};

            // How you want the results sorted in the resulting Cursor
            String sortOrder = DataEntry.COLUMN_NAME_ENTRY_ID + " ASC";

            //Define the where condition
            String where = "";
            String[] values = {};
            switch (tabNumber) {
                case 1:
                    where = "later=? and done=? and temp=?";
                    values = new String[]{"0", "0", "0"};
                    break;

                case 2:
                    where = "later=? and temp=?";
                    values = new String[]{"1", "0"};
                    break;

                case 3:
                    where = "done=? and temp=?";
                    values = new String[]{"1", "0"};
                    break;
            }

            Cursor cursor = null;
            try {
                cursor = db.query(
                        DataEntry.TABLE_NAME,  // The table to query
                        projection,                               // The columns to return
                        where,                                   // The columns for the WHERE clause
                        values,                      // The values for the WHERE clause
                        null,                                     // don't group the rows
                        null,                                     // don't filter by row groups
                        sortOrder                                 // The sort order
                );


                if (cursor.moveToLast()) {
                    lastOrderIndex = cursor.getInt(cursor.getColumnIndex(DataEntry.COLUMN_NAME_ENTRY_ID));
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }

        return lastOrderIndex;
    }

    /**
     * Get the temporary ideas (temp = 1)
     *
     * @return a list of their ids
     */
    public ArrayList<Integer> readTempIdeas() {
        SQLiteDatabase db = this.getReadableDatabase();
        String[] projection = {DataEntry._ID};

        ArrayList<Integer> temps = new ArrayList<>();
        Cursor cursor = null;
        try {
            cursor = db.query(
                    DataEntry.TABLE_NAME,  // The table to query
                    projection,                               // The columns to return
                    "temp=?",                                   // The columns for the WHERE clause
                    new String[]{"1"},                      // The values for the WHERE clause
                    null,                                     // don't group the rows
                    null,                                     // don't filter by row groups
                    null                                 // The sort order
            );


            //Scan the ideas and return everything
            if (cursor.moveToFirst()) {

                while (!cursor.isAfterLast()) {
                    int id = cursor.getInt(cursor.getColumnIndex(DataEntry._ID));
                    temps.add(id);
                    cursor.moveToNext();
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return temps;
    }

    /**
     * Search for ideas using a substring,
     * match can occur in the title or the note of the idea,
     * search is case insensitive
     *
     * @param sub
     * @return
     */
    public ArrayList<Pair<Integer, String>> searchIdeas(String sub) {
        if (!DataEntry.TABLE_NAME.equals("[]")) {

            SQLiteDatabase db = this.getReadableDatabase();

            // Only the text and id will be read
            String[] projection = {DataEntry._ID, DataEntry.COLUMN_NAME_TEXT, DataEntry.COLUMN_NAME_NOTE};

            // How you want the results sorted in the resulting Cursor
            String sortOrder = DataEntry.COLUMN_NAME_TEXT + " ASC";

            //Define the where condition, all not temps ideas
            String where = "temp=?";
            String[] values = new String[]{"0"};

            Cursor cursor = null;
            ArrayList<Pair<Integer, String>> ideas = new ArrayList<>();
            try {
                cursor = db.query(
                        DataEntry.TABLE_NAME,  // The table to query
                        projection,                               // The columns to return
                        where,                                   // The columns for the WHERE clause
                        values,                      // The values for the WHERE clause
                        null,                                     // don't group the rows
                        null,                                     // don't filter by row groups
                        sortOrder                                 // The sort order
                );


                Pair<Integer, String> pair;

                //Scan the ideas and return everything
                if (cursor.moveToFirst()) {

                    while (!cursor.isAfterLast()) {
                        String text = cursor.getString(cursor.getColumnIndex(DataEntry.COLUMN_NAME_TEXT));
                        String note = cursor.getString(cursor.getColumnIndex(DataEntry.COLUMN_NAME_NOTE));
                        int id = cursor.getInt(cursor.getColumnIndex(DataEntry._ID));

                        if (text.toLowerCase().contains(sub.toLowerCase()) || note.toLowerCase().contains(sub.toLowerCase())) {
                            pair = new Pair<>(id, text);
                            ideas.add(pair);
                        }
                        cursor.moveToNext();
                    }
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
            return ideas;
        }

        return new ArrayList<>();
    }


    //ORDER OPERATIONS

    /**
     * Reset the order indexes of the ideas to match the order displayed
     * Usefull after a manual reorder (long click)
     *
     * @param tabNumber
     */
    public void resetEntriesOrderAt(int tabNumber) {

        //Get the list with right order
        List<Pair<Integer, String>> itemList = adapters[tabNumber].getItemList();

        SQLiteDatabase db = this.getWritableDatabase();
        int indexOrder = 0;

        for (Pair<Integer, String> item : itemList) {
            ContentValues values = new ContentValues();
            values.put(DataEntry.COLUMN_NAME_ENTRY_ID, indexOrder);
            db.update(DataEntry.TABLE_NAME, values, "_id=" + item.first, null);
            indexOrder++;
        }

    }

    public void sortByAscPriorityAt(int tabNumber) {

        if (adapters[tabNumber] != null) {
            //Get the list with right order
            List<Pair<Integer, String>> itemList = adapters[tabNumber].getItemList();

            ArrayList<Integer> p1 = new ArrayList<>(), p2 = new ArrayList<>(), p3 = new ArrayList<>();

            //Separate the ideas by priority in 3 lists
            int priority = 1;
            int id = 0;
            for (Pair<Integer, String> item : itemList) {
                id = item.first;
                priority = getPriorityById(id);
                switch (priority) {
                    case 1:
                        p1.add(id);
                        break;

                    case 2:
                        p2.add(id);
                        break;

                    default:
                        p3.add(id);
                        break;
                }
            }

            //Go through the lists by ascendent priority and assign the order indexes
            SQLiteDatabase db = this.getWritableDatabase();
            int indexOrder = 0;
            ContentValues values;
            for (Integer i1 : p1) {
                values = new ContentValues();
                values.put(DataEntry.COLUMN_NAME_ENTRY_ID, indexOrder);
                db.update(DataEntry.TABLE_NAME, values, "_id=" + i1, null);
                indexOrder++;
            }
            for (Integer i2 : p2) {
                values = new ContentValues();
                values.put(DataEntry.COLUMN_NAME_ENTRY_ID, indexOrder);
                db.update(DataEntry.TABLE_NAME, values, "_id=" + i2, null);
                indexOrder++;
            }
            for (Integer i3 : p3) {
                values = new ContentValues();
                values.put(DataEntry.COLUMN_NAME_ENTRY_ID, indexOrder);
                db.update(DataEntry.TABLE_NAME, values, "_id=" + i3, null);
                indexOrder++;
            }
        }

    }

    public void sortByAscPriority() {
        for (int tab = 1; tab <= 3; tab++) {
            sortByAscPriorityAt(tab);
        }
        //Send the newly ordered lists for display
        notifyAllLists();
    }


}