package org.indywidualni.fblite.util.database;

import android.content.ContentValues;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.preference.PreferenceManager;
import android.util.Log;

import org.indywidualni.fblite.MyApplication;
import org.indywidualni.fblite.R;

import java.util.ArrayList;

public class OfflineDataSource {

    private static volatile OfflineDataSource instance;

    private SQLiteDatabase database;
    private MySQLiteHelper dbHelper;

    private final SharedPreferences preferences = PreferenceManager
            .getDefaultSharedPreferences(MyApplication.getContextOfApplication());

    private OfflineDataSource() {}

    public static OfflineDataSource getInstance() {
        if (instance == null) {
            synchronized (OfflineDataSource.class) {
                if (instance == null)
                    instance = new OfflineDataSource();
            }
        }
        return instance;
    }

    private void open() throws SQLException {
        if (dbHelper == null) {
            dbHelper = new MySQLiteHelper();
            database = dbHelper.getWritableDatabase();
        }
    }

    private void close() {
        if (database != null) {
            trimDatabase();
            dbHelper.close();
            dbHelper = null;
            database = null;
        }
    }

    public void trimDatabase() {
        // a database has to be opened first
        int maxPages = 10;
        try {  // just in case
            maxPages = Integer.parseInt(preferences.getString("offline_keep_max", "10"));
        } catch (NumberFormatException e) {
            Log.w("OfflineDataSource", e);
        }
        // delete the oldest rows leaving the latest maxPages rows
        database.execSQL("DELETE FROM Pages WHERE ROWID IN (" +
                "SELECT ROWID FROM Pages ORDER BY ROWID DESC LIMIT -1 OFFSET " + maxPages + ");");
    }

    public synchronized void insertPage(String url, String html) throws SQLException {
        open();

        ContentValues insertValues = new ContentValues();
        insertValues.put("url", url);
        insertValues.put("html", html);

        // insert or replace, the default one is a broken shit
        if (!rowExists(url))
            database.insert("Pages", null, insertValues);
        else
            database.replace("Pages", null, insertValues);

        close();
    }

    // insertPage helper, the database have to be open to use it
    private boolean rowExists(String url) {
        Cursor cursor = null;
        boolean exists = false;

        try {
            cursor = database.rawQuery("select 1 from Pages where url=?;", new String[] {url});
            exists = (cursor.getCount() > 0);
        } finally {
            if (cursor != null)
                cursor.close();
        }

        return exists;
    }

    public synchronized String getPage(String url) throws SQLException {
        open();
        Cursor cursor = null;
        String html = MyApplication.getContextOfApplication().getString(R.string.not_found_offline);

        try {
            cursor = database.rawQuery("SELECT html FROM Pages WHERE url=?;", new String[] { url });
            if(cursor.getCount() > 0) {
                cursor.moveToFirst();
                html = cursor.getString(cursor.getColumnIndex("html"));
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }

        close();
        return html;
    }

    public synchronized ArrayList<String> getAllPages() {
        open();
        Cursor cursor = null;
        ArrayList<String> list = new ArrayList<>();

        try {
            cursor = database.rawQuery("Select url from Pages ORDER BY ROWID DESC", new String[] {});
            if(cursor.getCount() > 0) {
                // retrieve the data to my custom model
                cursor.moveToFirst();

                while (!cursor.isAfterLast()) {
                    String page = cursorToPages(cursor);
                    list.add(page);
                    cursor.moveToNext();
                }
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }

        close();
        return list;
    }

    private String cursorToPages(Cursor cursor) {
        return cursor.getString(0);
    }

}