/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.providers.partnerbookmarks;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.UriMatcher;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Default partner bookmarks provider implementation of {@link PartnerBookmarksContract} API.
 * It reads the flat list of bookmarks and the name of the root partner
 * bookmarks folder using getResources() API.
 *
 * Sample resources structure:
 *     res/
 *         values/
 *             strings.xml
 *                  string name="bookmarks_folder_name"
 *                  string-array name="bookmarks"
 *                      item TITLE1
 *                      item URL1
 *                      item TITLE2
 *                      item URL2...
 *             bookmarks_icons.xml
 *                  array name="bookmark_preloads"
 *                      item @raw/favicon1
 *                      item @raw/touchicon1
 *                      item @raw/favicon2
 *                      item @raw/touchicon2
 *                      ...
 */
public class PartnerBookmarksProvider extends ContentProvider {
    private static final String TAG = "PartnerBookmarksProvider";

    // URI matcher
    private static final int URI_MATCH_BOOKMARKS = 1000;
    private static final int URI_MATCH_BOOKMARKS_ID = 1001;
    private static final int URI_MATCH_BOOKMARKS_FOLDER = 1002;
    private static final int URI_MATCH_BOOKMARKS_FOLDER_ID = 1003;
    private static final int URI_MATCH_BOOKMARKS_PARTNER_BOOKMARKS_FOLDER_ID = 1004;

    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    private static final Map<String, String> BOOKMARKS_PROJECTION_MAP
            = new HashMap<String, String>();

    // Default sort order for unsync'd bookmarks
    private static final String DEFAULT_BOOKMARKS_SORT_ORDER =
            PartnerBookmarksContract.Bookmarks.ID + " DESC, "
                    + PartnerBookmarksContract.Bookmarks.ID + " ASC";

    // Initial bookmark id when for getResources() importing
    // Make sure to fix tests if you are changing this
    private static final long FIXED_ID_PARTNER_BOOKMARKS_ROOT =
            PartnerBookmarksContract.Bookmarks.BOOKMARK_PARENT_ROOT_ID + 1;

    // DB table name
    private static final String TABLE_BOOKMARKS = "bookmarks";

    static {
        final UriMatcher matcher = URI_MATCHER;
        final String authority = PartnerBookmarksContract.AUTHORITY;
        matcher.addURI(authority, "bookmarks", URI_MATCH_BOOKMARKS);
        matcher.addURI(authority, "bookmarks/#", URI_MATCH_BOOKMARKS_ID);
        matcher.addURI(authority, "bookmarks/folder", URI_MATCH_BOOKMARKS_FOLDER);
        matcher.addURI(authority, "bookmarks/folder/#", URI_MATCH_BOOKMARKS_FOLDER_ID);
        matcher.addURI(authority, "bookmarks/folder/id",
                URI_MATCH_BOOKMARKS_PARTNER_BOOKMARKS_FOLDER_ID);
        // Projection maps
        Map<String, String> map = BOOKMARKS_PROJECTION_MAP;
        map.put(PartnerBookmarksContract.Bookmarks.ID,
                PartnerBookmarksContract.Bookmarks.ID);
        map.put(PartnerBookmarksContract.Bookmarks.TITLE,
                PartnerBookmarksContract.Bookmarks.TITLE);
        map.put(PartnerBookmarksContract.Bookmarks.URL,
                PartnerBookmarksContract.Bookmarks.URL);
        map.put(PartnerBookmarksContract.Bookmarks.TYPE,
                PartnerBookmarksContract.Bookmarks.TYPE);
        map.put(PartnerBookmarksContract.Bookmarks.PARENT,
                PartnerBookmarksContract.Bookmarks.PARENT);
        map.put(PartnerBookmarksContract.Bookmarks.FAVICON,
                PartnerBookmarksContract.Bookmarks.FAVICON);
        map.put(PartnerBookmarksContract.Bookmarks.TOUCHICON,
                PartnerBookmarksContract.Bookmarks.TOUCHICON);
    }

    private final class DatabaseHelper extends SQLiteOpenHelper {
        private static final String DATABASE_FILENAME = "partnerBookmarks.db";
        private static final int DATABASE_VERSION = 1;
        private static final String PREFERENCES_FILENAME = "pbppref";
        private static final String ACTIVE_CONFIGURATION_PREFNAME = "config";
        private final SharedPreferences sharedPreferences;

        public DatabaseHelper(Context context) {
            super(context, DATABASE_FILENAME, null, DATABASE_VERSION);
            sharedPreferences = context.getSharedPreferences(
                    PREFERENCES_FILENAME, Context.MODE_PRIVATE);
        }

        private String getConfigSignature(Configuration config) {
            return "mmc=" + Integer.toString(config.mcc)
                    + "-mnc=" + Integer.toString(config.mnc)
                    + "-loc=" + config.locale.toString();
        }

        public synchronized void prepareForConfiguration(Configuration config) {
            final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
            String newSignature = getConfigSignature(config);
            String activeSignature =
                    sharedPreferences.getString(ACTIVE_CONFIGURATION_PREFNAME, null);
            if (activeSignature == null || !activeSignature.equals(newSignature)) {
                db.delete(TABLE_BOOKMARKS, null, null);
                if (!createDefaultBookmarks(db)) {
                    // Failure to read/insert bookmarks should be treated as "no bookmarks"
                    db.delete(TABLE_BOOKMARKS, null, null);
                }
            }
        }

        private void setActiveConfiguration(Configuration config) {
            Editor editor = sharedPreferences.edit();
            editor.putString(ACTIVE_CONFIGURATION_PREFNAME, getConfigSignature(config));
            editor.apply();
        }

        private void createTable(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE " + TABLE_BOOKMARKS + "(" +
                    PartnerBookmarksContract.Bookmarks.ID +
                    " INTEGER NOT NULL DEFAULT 0," +
                    PartnerBookmarksContract.Bookmarks.TITLE +
                    " TEXT," +
                    PartnerBookmarksContract.Bookmarks.URL +
                    " TEXT," +
                    PartnerBookmarksContract.Bookmarks.TYPE +
                    " INTEGER NOT NULL DEFAULT 0," +
                    PartnerBookmarksContract.Bookmarks.PARENT +
                    " INTEGER," +
                    PartnerBookmarksContract.Bookmarks.FAVICON +
                    " BLOB," +
                    PartnerBookmarksContract.Bookmarks.TOUCHICON +
                    " BLOB" + ");");
        }

        private void dropTable(SQLiteDatabase db) {
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_BOOKMARKS);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            synchronized (this) {
                createTable(db);
                if (!createDefaultBookmarks(db)) {
                    // Failure to read/insert bookmarks should be treated as "no bookmarks"
                    dropTable(db);
                    createTable(db);
                }
            }
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            dropTable(db);
            onCreate(db);
        }

        @Override
        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            dropTable(db);
            onCreate(db);
        }

        private boolean createDefaultBookmarks(SQLiteDatabase db) {
            Resources res = getContext().getResources();
            try {
                //CharSequence bookmarksFolderName = res.getText(R.string.bookmarks_folder_name);
                CharSequence bookmarksFolderName = CarrierBrowserUtils.getCarrierBookMarksFolderName(getContext());
                final CharSequence[] bookmarks = CarrierBrowserUtils.getCarrierBookMark(getContext());
                if (bookmarks.length >= 1) {
                    if (bookmarksFolderName.length() < 1) {
                        Log.i(TAG, "bookmarks_folder_name was not specified; bailing out");
                        return false;
                    }
                    if (!addRootFolder(db,
                            FIXED_ID_PARTNER_BOOKMARKS_ROOT, bookmarksFolderName.toString())) {
                        Log.i(TAG, "failed to insert root folder; bailing out");
                        return false;
                    }
                    if (!addDefaultBookmarks(db,
                            FIXED_ID_PARTNER_BOOKMARKS_ROOT, FIXED_ID_PARTNER_BOOKMARKS_ROOT + 1)) {
                        Log.i(TAG, "failed to insert bookmarks; bailing out");
                        return false;
                    }
                }
                setActiveConfiguration(res.getConfiguration());
            } catch (android.content.res.Resources.NotFoundException e) {
                Log.i(TAG, "failed to fetch resources; bailing out");
                return false;
            }
            return true;
        }

        private boolean addRootFolder(SQLiteDatabase db, long id, String bookmarksFolderName) {
            ContentValues values = new ContentValues();
            values.put(PartnerBookmarksContract.Bookmarks.ID, id);
            values.put(PartnerBookmarksContract.Bookmarks.TITLE,
                    bookmarksFolderName);
            values.put(PartnerBookmarksContract.Bookmarks.PARENT,
                    PartnerBookmarksContract.Bookmarks.BOOKMARK_PARENT_ROOT_ID);
            values.put(PartnerBookmarksContract.Bookmarks.TYPE,
                    PartnerBookmarksContract.Bookmarks.BOOKMARK_TYPE_FOLDER);
            return db.insertOrThrow(TABLE_BOOKMARKS, null, values) != -1;
        }

        private boolean addDefaultBookmarks(SQLiteDatabase db, long parentId, long firstBookmarkId) {
            long bookmarkId = firstBookmarkId;
            Resources res = getContext().getResources();
            final CharSequence[] bookmarks = CarrierBrowserUtils.getCarrierBookMark(getContext());
            int size = bookmarks.length;
            TypedArray preloads = res.obtainTypedArray(R.array.bookmark_preloads);
            DatabaseUtils.InsertHelper insertHelper = null;
            try {
                insertHelper = new DatabaseUtils.InsertHelper(db, TABLE_BOOKMARKS);
                final int idColumn = insertHelper.getColumnIndex(
                        PartnerBookmarksContract.Bookmarks.ID);
                final int titleColumn = insertHelper.getColumnIndex(
                        PartnerBookmarksContract.Bookmarks.TITLE);
                final int urlColumn = insertHelper.getColumnIndex(
                        PartnerBookmarksContract.Bookmarks.URL);
                final int typeColumn = insertHelper.getColumnIndex(
                        PartnerBookmarksContract.Bookmarks.TYPE);
                final int parentColumn = insertHelper.getColumnIndex(
                        PartnerBookmarksContract.Bookmarks.PARENT);
                final int faviconColumn = insertHelper.getColumnIndex(
                        PartnerBookmarksContract.Bookmarks.FAVICON);
                final int touchiconColumn = insertHelper.getColumnIndex(
                        PartnerBookmarksContract.Bookmarks.TOUCHICON);

                for (int i = 0; i + 1 < size; i = i + 2) {
                    CharSequence bookmarkDestination = bookmarks[i + 1];

                    String bookmarkTitle = bookmarks[i].toString();
                    String bookmarkUrl = bookmarkDestination.toString();
                    byte[] favicon = null;
                    if (i < preloads.length()) {
                        int faviconId = preloads.getResourceId(i, 0);
                        try {
                            favicon = readRaw(res, faviconId);
                        } catch (IOException e) {
                            Log.i(TAG, "Failed to read favicon for " + bookmarkTitle, e);
                        }
                    }
                    byte[] touchicon = null;
                    if (i + 1 < preloads.length()) {
                        int touchiconId = preloads.getResourceId(i + 1, 0);
                        try {
                            touchicon = readRaw(res, touchiconId);
                        } catch (IOException e) {
                            Log.i(TAG, "Failed to read touchicon for " + bookmarkTitle, e);
                        }
                    }
                    insertHelper.prepareForInsert();
                    insertHelper.bind(idColumn, bookmarkId);
                    insertHelper.bind(titleColumn, bookmarkTitle);
                    insertHelper.bind(urlColumn, bookmarkUrl);
                    insertHelper.bind(typeColumn,
                            PartnerBookmarksContract.Bookmarks.BOOKMARK_TYPE_BOOKMARK);
                    insertHelper.bind(parentColumn, parentId);
                    if (favicon != null) {
                        insertHelper.bind(faviconColumn, favicon);
                    }
                    if (touchicon != null) {
                        insertHelper.bind(touchiconColumn, touchicon);
                    }
                    bookmarkId++;
                    if (insertHelper.execute() == -1) {
                        Log.i(TAG, "Failed to insert bookmark " + bookmarkTitle);
                        return false;
                    }
                }
            } finally {
                preloads.recycle();
                insertHelper.close();
            }
            return true;
        }

        private byte[] readRaw(Resources res, int id) throws IOException {
            if (id == 0) return null;
            InputStream is = res.openRawResource(id);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                byte[] buf = new byte[4096];
                int read;
                while ((read = is.read(buf)) > 0) {
                    bos.write(buf, 0, read);
                }
                bos.flush();
                return bos.toByteArray();
            } finally {
                is.close();
                bos.close();
            }
        }
    }

    private DatabaseHelper mOpenHelper;

    @Override
    public boolean onCreate() {
        mOpenHelper = new DatabaseHelper(getContext());
        return true;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        mOpenHelper.prepareForConfiguration(getContext().getResources().getConfiguration());
    }

    @Override
    public Cursor query(Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder) {
        final int match = URI_MATCHER.match(uri);
        mOpenHelper.prepareForConfiguration(getContext().getResources().getConfiguration());
        final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        String limit = uri.getQueryParameter(PartnerBookmarksContract.PARAM_LIMIT);
        String groupBy = uri.getQueryParameter(PartnerBookmarksContract.PARAM_GROUP_BY);
        switch (match) {
            case URI_MATCH_BOOKMARKS_FOLDER_ID:
            case URI_MATCH_BOOKMARKS_ID:
            case URI_MATCH_BOOKMARKS: {
                if (match == URI_MATCH_BOOKMARKS_ID) {
                    // Tack on the ID of the specific bookmark requested
                    selection = DatabaseUtils.concatenateWhere(selection,
                            TABLE_BOOKMARKS + "." +
                                    PartnerBookmarksContract.Bookmarks.ID + "=?");
                    selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
                            new String[] { Long.toString(ContentUris.parseId(uri)) });
                } else if (match == URI_MATCH_BOOKMARKS_FOLDER_ID) {
                    // Tack on the ID of the specific folder requested
                    selection = DatabaseUtils.concatenateWhere(selection,
                            TABLE_BOOKMARKS + "." +
                                    PartnerBookmarksContract.Bookmarks.PARENT + "=?");
                    selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
                            new String[] { Long.toString(ContentUris.parseId(uri)) });
                }
                // Set a default sort order if one isn't specified
                if (TextUtils.isEmpty(sortOrder)) {
                    sortOrder = DEFAULT_BOOKMARKS_SORT_ORDER;
                }
                qb.setProjectionMap(BOOKMARKS_PROJECTION_MAP);
                qb.setTables(TABLE_BOOKMARKS);
                break;
            }

            case URI_MATCH_BOOKMARKS_FOLDER: {
                qb.setTables(TABLE_BOOKMARKS);
                String[] args;
                String query;
                // Set a default sort order if one isn't specified
                if (TextUtils.isEmpty(sortOrder)) {
                    sortOrder = DEFAULT_BOOKMARKS_SORT_ORDER;
                }
                qb.setProjectionMap(BOOKMARKS_PROJECTION_MAP);
                String where = PartnerBookmarksContract.Bookmarks.PARENT + "=?";
                where = DatabaseUtils.concatenateWhere(where, selection);
                args = new String[] { Long.toString(FIXED_ID_PARTNER_BOOKMARKS_ROOT) };
                if (selectionArgs != null) {
                    args = DatabaseUtils.appendSelectionArgs(args, selectionArgs);
                }
                query = qb.buildQuery(projection, where, null, null, sortOrder, null);
                Cursor cursor = db.rawQuery(query, args);
                return cursor;
            }

            case URI_MATCH_BOOKMARKS_PARTNER_BOOKMARKS_FOLDER_ID: {
                MatrixCursor c = new MatrixCursor(
                        new String[] {PartnerBookmarksContract.Bookmarks.ID});
                c.newRow().add(FIXED_ID_PARTNER_BOOKMARKS_ROOT);
                return c;
            }

            default: {
                throw new UnsupportedOperationException("Unknown URL " + uri.toString());
            }
        }

        return qb.query(db, projection, selection, selectionArgs, groupBy, null, sortOrder, limit);
    }

    @Override
    public String getType(Uri uri) {
        final int match = URI_MATCHER.match(uri);
        if (match == UriMatcher.NO_MATCH) return null;
        return PartnerBookmarksContract.Bookmarks.CONTENT_ITEM_TYPE;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }
}
