package com.android.launcher3.provider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;

import com.android.launcher3.LauncherProvider;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.NoLocaleSQLiteHelper;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class ManagerAppProvider extends ContentProvider {


    public static final String TAG = "ManagerAppProvider";
    public static final String TABLE_NAME = "management_info";

    public static final int SCHEMA_VERSION = 2;

    protected DatabaseHelper mOpenHelper;


    public static final String EMPTY_DATABASE_CREATED = "EMPTY_MANAGEMENT_DATABASE_CREATED";

    public static String AUTHORITY;

    @Override
    public boolean onCreate() {
        AUTHORITY = (getContext().getApplicationInfo().packageName + ".management").intern();
        createDbIfNotExists();
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        createDbIfNotExists();

        LauncherProvider.SqlArguments args = new LauncherProvider.SqlArguments(uri, selection, selectionArgs);
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        qb.setTables(args.table);

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        Cursor result = qb.query(db, projection, args.where, args.args, null, null, sortOrder);
        result.setNotificationUri(getContext().getContentResolver(), uri);

        return result;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        LauncherProvider.SqlArguments args = new LauncherProvider.SqlArguments(uri, null, null);
        if (TextUtils.isEmpty(args.where)) {
            return "vnd.android.cursor.dir/" + args.table;
        } else {
            return "vnd.android.cursor.item/" + args.table;
        }
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        createDbIfNotExists();
        LauncherProvider.SqlArguments args = new LauncherProvider.SqlArguments(uri);

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();

        final long rowId = db.insert(args.table, null, values);
        if (rowId < 0) return null;

        uri = ContentUris.withAppendedId(uri, rowId);
        return uri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        createDbIfNotExists();
        LauncherProvider.SqlArguments args = new LauncherProvider.SqlArguments(uri, selection, selectionArgs);

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();


        int count = db.delete(args.table, args.where, args.args);
        return count;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        createDbIfNotExists();
        LauncherProvider.SqlArguments args = new LauncherProvider.SqlArguments(uri, selection, selectionArgs);

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        int count = db.update(args.table, values, args.where, args.args);

        return count;
    }


    @Nullable
    @Override
    public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle extras) {

        switch (method) {
            case METHOD_GENERATENEWITEMID:
                Bundle result = new Bundle();
                result.putLong(EXTRA_VALUE, mOpenHelper.generateNewItemId());
                return result;
        }
        return super.call(method, arg, extras);
    }


    public static final String METHOD_GENERATENEWITEMID = "generateNewItemId";


    public static final String EXTRA_VALUE = "value";

    public long generateNewItemId() {
        return mOpenHelper.generateNewItemId();
    }


    /**
     * Overridden in tests
     */
    protected synchronized void createDbIfNotExists() {
        if (mOpenHelper == null) {
            mOpenHelper = new DatabaseHelper(getContext(), "management.db", SCHEMA_VERSION);

            mOpenHelper.createEmptyDBIFNotExists(mOpenHelper.getWritableDatabase());

        }
    }


    public static class DatabaseHelper extends NoLocaleSQLiteHelper {

        public static final String TAG = "DatabaseHelper";

        public static final Uri CONTENT_URI = Uri.parse("content://" +
                ManagerAppProvider.AUTHORITY + "/" + TABLE_NAME);

        private final Context mContext;
        private long mMaxItemId = -1;

        public DatabaseHelper(Context context, String name, int version) {
            super(context, name, version);
            mContext = context;
            initIds();
        }

        protected void initIds() {
            // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
            // the DB here
            if (mMaxItemId == -1) {
                mMaxItemId = initializeMaxItemId(getWritableDatabase());
            }
        }

        private long initializeMaxItemId(SQLiteDatabase db) {
            return getMaxId(db, ManagerAppProvider.TABLE_NAME);
        }


        static long getMaxId(SQLiteDatabase db, String table) {
            Cursor c = db.rawQuery("SELECT MAX(_id) FROM " + table, null);
            // get the result
            long id = -1;
            if (c != null && c.moveToNext()) {
                id = c.getLong(0);
            }
            if (c != null) {
                c.close();
            }

            if (id == -1) {
                throw new RuntimeException("Error: could not query max id in " + table);
            }

            return id;
        }


        private boolean tableExists(String tableName) {
            Cursor c = getReadableDatabase().query(
                    true, "sqlite_master", new String[]{"tbl_name"},
                    "tbl_name = ?", new String[]{tableName},
                    null, null, null, null, null);
            try {
                return c.getCount() > 0;
            } finally {
                c.close();
            }
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

            mMaxItemId = 1;

            addManagementTable(db, false);


            // Fresh and clean launcher DB.
            mMaxItemId = initializeMaxItemId(db);

            Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
        }


        private void addManagementTable(SQLiteDatabase db, boolean optional) {
            String ifNotExists = optional ? " IF NOT EXISTS " : "";
            db.execSQL("CREATE TABLE " + ifNotExists + ManagerAppProvider.TABLE_NAME + " (" +
                    ManagementColumns._ID + " INTEGER PRIMARY KEY," +
                    ManagementColumns.PACKAGENAME + " TEXT," +
                    ManagementColumns.USE_TYPE + " INTEGER NOT NULL DEFAULT 0," +
                    ManagementColumns.LOCK + " INTEGER NOT NULL DEFAULT 0," +
                    ManagementColumns.ENDTIMESTAMP + " LONG NOT NULL DEFAULT 0" +
                    ");");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

            createEmptyDB(db);

            if(oldVersion == 1 && newVersion == 2){
                //从版本1到版本2时，增加了一个字段 desc
                String sql = "alter table ["+TABLE_NAME+"] add [ManagementColumns.ENDTIMESTAMP] long";
                db.execSQL(sql);
            }
        }


        /**
         * Clears all the data for a fresh start.
         */
        public void createEmptyDB(SQLiteDatabase db) {
            try (LauncherDbUtils.SQLiteTransaction t = new LauncherDbUtils.SQLiteTransaction(db)) {
                db.execSQL("DROP TABLE IF EXISTS " + ManagerAppProvider.TABLE_NAME);
                onCreate(db);
                t.commit();
            }
        }


        /**
         * Clears all the data for a fresh start.
         */
        public void createEmptyDBIFNotExists(SQLiteDatabase db) {
            try (LauncherDbUtils.SQLiteTransaction t = new LauncherDbUtils.SQLiteTransaction(db)) {
                addManagementTable(db, true);
                t.commit();
            }
        }

        public long generateNewItemId() {
            if (mMaxItemId < 0) {
                throw new RuntimeException("Error: max item id was not initialized");
            }
            mMaxItemId += 1;
            return mMaxItemId;
        }

        public void checkId(String table, ContentValues values) {
            long id = values.getAsLong(ManagementColumns._ID);
            mMaxItemId = Math.max(id, mMaxItemId);

        }

    }

    public static class ManagementColumns {
        /**
         * The unique ID for a row.
         * <P>Type: INTEGER (long)</P>
         */
        public static final String _ID = "_id";


        public static final String PACKAGENAME = "package";


        /**
         * 桌面组件的显示状态
         * 正常使用 无边框
         * 游戏管控类 黄色边框
         * 未分类 灰色边框
         */
        public static final String USE_TYPE = "use_type";


        /**
         * 应用是否是锁定状态
         */
        public static final String LOCK = "lock";

        /**
         * 应用使用的截止时间戳
         */
        public static final String ENDTIMESTAMP = "endtimestamp";
    }
}
