/*
 * Copyright (C) 2011 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.contacts;

import static android.Manifest.permission.ADD_VOICEMAIL;
import static android.Manifest.permission.READ_VOICEMAIL;

import android.content.ComponentName;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.database.DatabaseUtils.InsertHelper;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Binder;
import android.provider.CallLog.Calls;
import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Status;
import android.provider.VoicemailContract.Voicemails;
import android.util.ArraySet;
import android.util.Log;

import com.android.common.io.MoreCloseables;
import com.android.providers.contacts.CallLogDatabaseHelper.Tables;
import com.android.providers.contacts.util.DbQueryUtils;

import com.google.android.collect.Lists;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * An implementation of {@link DatabaseModifier} for voicemail related tables which additionally
 * generates necessary notifications after the modification operation is performed.
 * The class generates notifications for both voicemail as well as call log URI depending on which
 * of then got affected by the change.
 */
public class DbModifierWithNotification implements DatabaseModifier {
    private static final String TAG = "DbModifierWithNotify";

    private static final String[] PROJECTION = new String[] {
            VoicemailContract.SOURCE_PACKAGE_FIELD
    };
    private static final int SOURCE_PACKAGE_COLUMN_INDEX = 0;
    private static final String NON_NULL_SOURCE_PACKAGE_SELECTION =
            VoicemailContract.SOURCE_PACKAGE_FIELD + " IS NOT NULL";
    private static final String NOT_DELETED_SELECTION =
            Voicemails.DELETED + " == 0";
    private final String mTableName;
    private final SQLiteDatabase mDb;
    private final InsertHelper mInsertHelper;
    private final Context mContext;
    private final Uri mBaseUri;
    private final boolean mIsCallsTable;
    private final VoicemailPermissions mVoicemailPermissions;


    public DbModifierWithNotification(String tableName, SQLiteDatabase db, Context context) {
        this(tableName, db, null, context);
    }

    public DbModifierWithNotification(String tableName, InsertHelper insertHelper,
            Context context) {
        this(tableName, null, insertHelper, context);
    }

    private DbModifierWithNotification(String tableName, SQLiteDatabase db,
            InsertHelper insertHelper, Context context) {
        mTableName = tableName;
        mDb = db;
        mInsertHelper = insertHelper;
        mContext = context;
        mBaseUri = mTableName.equals(Tables.VOICEMAIL_STATUS) ?
                Status.CONTENT_URI : Voicemails.CONTENT_URI;
        mIsCallsTable = mTableName.equals(Tables.CALLS);
        mVoicemailPermissions = new VoicemailPermissions(mContext);
    }

    @Override
    public long insert(String table, String nullColumnHack, ContentValues values) {
        Set<String> packagesModified = getModifiedPackages(values);
        if (mIsCallsTable) {
            values.put(Calls.LAST_MODIFIED, getTimeMillis());
        }
        long rowId = mDb.insert(table, nullColumnHack, values);
        if (rowId > 0 && packagesModified.size() != 0) {
            notifyVoicemailChangeOnInsert(ContentUris.withAppendedId(mBaseUri, rowId),
                    packagesModified);
        }
        if (rowId > 0 && mIsCallsTable) {
            notifyCallLogChange();
        }
        return rowId;
    }

    @Override
    public long insert(ContentValues values) {
        Set<String> packagesModified = getModifiedPackages(values);
        if (mIsCallsTable) {
            values.put(Calls.LAST_MODIFIED, getTimeMillis());
        }
        long rowId = mInsertHelper.insert(values);
        if (rowId > 0 && packagesModified.size() != 0) {
            notifyVoicemailChangeOnInsert(
                    ContentUris.withAppendedId(mBaseUri, rowId), packagesModified);
        }
        if (rowId > 0 && mIsCallsTable) {
            notifyCallLogChange();
        }
        return rowId;
    }

    private void notifyCallLogChange() {
        mContext.getContentResolver().notifyChange(Calls.CONTENT_URI, null, false);

        Intent intent = new Intent("com.android.internal.action.CALL_LOG_CHANGE");
        intent.setComponent(new ComponentName("com.android.calllogbackup",
                "com.android.calllogbackup.CallLogChangeReceiver"));

        if (!mContext.getPackageManager().queryBroadcastReceivers(intent, 0).isEmpty()) {
            mContext.sendBroadcast(intent);
        }
    }

    private void notifyVoicemailChangeOnInsert(Uri notificationUri, Set<String> packagesModified) {
        if (mIsCallsTable) {
            notifyVoicemailChange(notificationUri, packagesModified,
                    VoicemailContract.ACTION_NEW_VOICEMAIL, Intent.ACTION_PROVIDER_CHANGED);
        } else {
            notifyVoicemailChange(notificationUri, packagesModified,
                    Intent.ACTION_PROVIDER_CHANGED);
        }
    }

    @Override
    public int update(Uri uri, String table, ContentValues values, String whereClause,
            String[] whereArgs) {
        Set<String> packagesModified = getModifiedPackages(whereClause, whereArgs);
        packagesModified.addAll(getModifiedPackages(values));

        boolean isVoicemail = packagesModified.size() != 0;

        boolean hasMarkedRead = false;
        if (mIsCallsTable) {
            if (values.containsKey(Voicemails.DELETED)
                    && !values.getAsBoolean(Voicemails.DELETED)) {
                values.put(Calls.LAST_MODIFIED, getTimeMillis());
            } else {
                updateLastModified(table, whereClause, whereArgs);
            }
            if (isVoicemail) {
                // If a calling package is modifying its own entries, it means that the change came
                // from the server and thus is synced or "clean". Otherwise, it means that a local
                // change is being made to the database, so the entries should be marked as "dirty"
                // so that the corresponding sync adapter knows they need to be synced.
                int isDirty;
                Integer callerSetDirty = values.getAsInteger(Voicemails.DIRTY);
                if (callerSetDirty != null) {
                    // Respect the calling package if it sets the dirty flag
                    isDirty = callerSetDirty == 0 ? 0 : 1;
                } else {
                    isDirty = isSelfModifyingOrInternal(packagesModified) ? 0 : 1;
                }
                values.put(VoicemailContract.Voicemails.DIRTY, isDirty);

                if (isDirty == 0 && values.containsKey(Calls.IS_READ) && getAsBoolean(values,
                        Calls.IS_READ)) {
                    // If the server has set the IS_READ, it should also unset the new flag
                    if (!values.containsKey(Calls.NEW)) {
                        values.put(Calls.NEW, 0);
                        hasMarkedRead = true;
                    }
                }
            }
        }

        int count = mDb.update(table, values, whereClause, whereArgs);
        if (count > 0 && isVoicemail) {
            notifyVoicemailChange(mBaseUri, packagesModified, Intent.ACTION_PROVIDER_CHANGED);
        }
        if (count > 0 && mIsCallsTable) {
            notifyCallLogChange();
        }
        if (hasMarkedRead) {
            // A "New" voicemail has been marked as read by the server. This voicemail is no longer
            // new but the content consumer might still think it is. ACTION_NEW_VOICEMAIL should
            // trigger a rescan of new voicemails.
            mContext.sendBroadcast(
                    new Intent(VoicemailContract.ACTION_NEW_VOICEMAIL, uri),
                    READ_VOICEMAIL);
        }
        return count;
    }

    private void updateLastModified(String table, String whereClause, String[] whereArgs) {
        ContentValues values = new ContentValues();
        values.put(Calls.LAST_MODIFIED, getTimeMillis());

        mDb.update(table, values,
                DbQueryUtils.concatenateClauses(NOT_DELETED_SELECTION, whereClause),
                whereArgs);
    }

    @Override
    public int delete(String table, String whereClause, String[] whereArgs) {
        Set<String> packagesModified = getModifiedPackages(whereClause, whereArgs);
        boolean isVoicemail = packagesModified.size() != 0;

        // If a deletion is made by a package that is not the package that inserted the voicemail,
        // this means that the user deleted the voicemail. However, we do not want to delete it from
        // the database until after the server has been notified of the deletion. To ensure this,
        // mark the entry as "deleted"--deleted entries should be hidden from the user.
        // Once the changes are synced to the server, delete will be called again, this time
        // removing the rows from the table.
        // If the deletion is being made by the package that inserted the voicemail or by
        // CP2 (cleanup after uninstall), then we don't need to wait for sync, so just delete it.
        final int count;
        if (mIsCallsTable && isVoicemail && !isSelfModifyingOrInternal(packagesModified)) {
            ContentValues values = new ContentValues();
            values.put(VoicemailContract.Voicemails.DIRTY, 1);
            values.put(VoicemailContract.Voicemails.DELETED, 1);
            values.put(VoicemailContract.Voicemails.LAST_MODIFIED, getTimeMillis());
            count = mDb.update(table, values, whereClause, whereArgs);
        } else {
            count = mDb.delete(table, whereClause, whereArgs);
        }

        if (count > 0 && isVoicemail) {
            notifyVoicemailChange(mBaseUri, packagesModified, Intent.ACTION_PROVIDER_CHANGED);
        }
        if (count > 0 && mIsCallsTable) {
            notifyCallLogChange();
        }
        return count;
    }

    /**
     * Returns the set of packages affected when a modify operation is run for the specified
     * where clause. When called from an insert operation an empty set returned by this method
     * implies (indirectly) that this does not affect any voicemail entry, as a voicemail entry is
     * always expected to have the source package field set.
     */
    private Set<String> getModifiedPackages(String whereClause, String[] whereArgs) {
        Set<String> modifiedPackages = new ArraySet<>();
        Cursor cursor = mDb.query(mTableName, PROJECTION,
                DbQueryUtils.concatenateClauses(NON_NULL_SOURCE_PACKAGE_SELECTION, whereClause),
                whereArgs, null, null, null);
        while(cursor.moveToNext()) {
            modifiedPackages.add(cursor.getString(SOURCE_PACKAGE_COLUMN_INDEX));
        }
        MoreCloseables.closeQuietly(cursor);
        return modifiedPackages;
    }

    /**
     * Returns the source package that gets affected (in an insert/update operation) by the supplied
     * content values. An empty set returned by this method also implies (indirectly) that this does
     * not affect any voicemail entry, as a voicemail entry is always expected to have the source
     * package field set.
     */
    private Set<String> getModifiedPackages(ContentValues values) {
        Set<String> impactedPackages = new ArraySet<>();
        if(values.containsKey(VoicemailContract.SOURCE_PACKAGE_FIELD)) {
            impactedPackages.add(values.getAsString(VoicemailContract.SOURCE_PACKAGE_FIELD));
        }
        return impactedPackages;
    }

    /**
     * @param packagesModified source packages that inserted the voicemail that is being modified
     * @return {@code true} if the caller is modifying its own voicemail, or this is an internal
     *         transaction, {@code false} otherwise.
     */
    private boolean isSelfModifyingOrInternal(Set<String> packagesModified) {
        final Collection<String> callingPackages = getCallingPackages();
        if (callingPackages == null) {
            return false;
        }
        // The last clause has the same effect as doing Process.myUid() == Binder.getCallingUid(),
        // but allows us to mock the results for testing.
        return packagesModified.size() == 1 && (callingPackages.contains(
                Iterables.getOnlyElement(packagesModified))
                        || callingPackages.contains(mContext.getPackageName()));
    }

    private void notifyVoicemailChange(Uri notificationUri, Set<String> modifiedPackages,
            String... intentActions) {
        // Notify the observers.
        // Must be done only once, even if there are multiple broadcast intents.
        mContext.getContentResolver().notifyChange(notificationUri, null, true);
        Collection<String> callingPackages = getCallingPackages();
        // Now fire individual intents.
        for (String intentAction : intentActions) {
            // self_change extra should be included only for provider_changed events.
            boolean includeSelfChangeExtra = intentAction.equals(Intent.ACTION_PROVIDER_CHANGED);
            for (ComponentName component :
                    getBroadcastReceiverComponents(intentAction, notificationUri)) {
                // Ignore any package that is not affected by the change and don't have full access
                // either.
                if (!modifiedPackages.contains(component.getPackageName()) &&
                        !mVoicemailPermissions.packageHasReadAccess(
                                component.getPackageName())) {
                    continue;
                }

                Intent intent = new Intent(intentAction, notificationUri);
                intent.setComponent(component);
                if (includeSelfChangeExtra && callingPackages != null) {
                    intent.putExtra(VoicemailContract.EXTRA_SELF_CHANGE,
                            callingPackages.contains(component.getPackageName()));
                }
                String permissionNeeded = modifiedPackages.contains(component.getPackageName()) ?
                        ADD_VOICEMAIL : READ_VOICEMAIL;
                mContext.sendBroadcast(intent, permissionNeeded);
                Log.v(TAG, String.format("Sent intent. act:%s, url:%s, comp:%s, perm:%s," +
                        " self_change:%s", intent.getAction(), intent.getData(),
                        component.getClassName(), permissionNeeded,
                        intent.hasExtra(VoicemailContract.EXTRA_SELF_CHANGE) ?
                                intent.getBooleanExtra(VoicemailContract.EXTRA_SELF_CHANGE, false) :
                                        null));
            }
        }
    }

    /** Determines the components that can possibly receive the specified intent. */
    private List<ComponentName> getBroadcastReceiverComponents(String intentAction, Uri uri) {
        Intent intent = new Intent(intentAction, uri);
        List<ComponentName> receiverComponents = new ArrayList<ComponentName>();
        // For broadcast receivers ResolveInfo.activityInfo is the one that is populated.
        for (ResolveInfo resolveInfo :
                mContext.getPackageManager().queryBroadcastReceivers(intent, 0)) {
            ActivityInfo activityInfo = resolveInfo.activityInfo;
            receiverComponents.add(new ComponentName(activityInfo.packageName, activityInfo.name));
        }
        return receiverComponents;
    }

    /**
     * Returns the package names of the calling process. If the calling process has more than
     * one packages, this returns them all
     */
    private Collection<String> getCallingPackages() {
        int caller = Binder.getCallingUid();
        if (caller == 0) {
            return null;
        }
        return Lists.newArrayList(mContext.getPackageManager().getPackagesForUid(caller));
    }

    /**
     * A variant of {@link ContentValues#getAsBoolean(String)} that also treat the string "0" as
     * false and other integer string as true. 0, 1, false, true, "0", "1", "false", "true" might
     * all be inserted into the ContentValues as a boolean, but "0" and "1" are not handled by
     * {@link ContentValues#getAsBoolean(String)}
     */
    private static Boolean getAsBoolean(ContentValues values, String key) {
        Object value = values.get(key);
        if (value instanceof CharSequence) {
            try {
                int intValue = Integer.parseInt(value.toString());
                return intValue != 0;
            } catch (NumberFormatException nfe) {
                // Do nothing.
            }
        }
        return values.getAsBoolean(key);
    }

    private long getTimeMillis() {
        if (CallLogProvider.getTimeForTestMillis() == null) {
            return System.currentTimeMillis();
        }
        return CallLogProvider.getTimeForTestMillis();
    }
}
