/*
 * 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 com.android.providers.contacts.util.DbQueryUtils.checkForSupportedColumns;
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.CallLog.Calls;
import android.provider.OpenableColumns;
import android.provider.VoicemailContract.Voicemails;
import android.util.ArraySet;
import android.util.Log;

import com.android.common.content.ProjectionMap;
import com.android.providers.contacts.VoicemailContentProvider.UriData;
import com.android.providers.contacts.util.CloseUtils;

import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * Implementation of {@link VoicemailTable.Delegate} for the voicemail content table.
 */
public class VoicemailContentTable implements VoicemailTable.Delegate {

    private static final String TAG = "VmContentProvider";
    private final ProjectionMap mVoicemailProjectionMap;

    /**
     * The private directory in which to store the data associated with the voicemail.
     */
    private static final String DATA_DIRECTORY = "voicemail-data";

    private static final String[] FILENAME_ONLY_PROJECTION = new String[] {Voicemails._DATA};

    public static final ImmutableSet<String> ALLOWED_COLUMNS = new ImmutableSet.Builder<String>()
            .add(Voicemails._ID)
            .add(Voicemails.NUMBER)
            .add(Voicemails.DATE)
            .add(Voicemails.DURATION)
            .add(Voicemails.NEW)
            .add(Voicemails.IS_READ)
            .add(Voicemails.TRANSCRIPTION)
            .add(Voicemails.TRANSCRIPTION_STATE)
            .add(Voicemails.STATE)
            .add(Voicemails.SOURCE_DATA)
            .add(Voicemails.SOURCE_PACKAGE)
            .add(Voicemails.HAS_CONTENT)
            .add(Voicemails.PHONE_ACCOUNT_COMPONENT_NAME)
            .add(Voicemails.PHONE_ACCOUNT_ID)
            .add(Voicemails.MIME_TYPE)
            .add(Voicemails.DIRTY)
            .add(Voicemails.DELETED)
            .add(Voicemails.LAST_MODIFIED)
            .add(Voicemails.BACKED_UP)
            .add(Voicemails.RESTORED)
            .add(Voicemails.ARCHIVED)
            .add(Voicemails.IS_OMTP_VOICEMAIL)
            .add(OpenableColumns.DISPLAY_NAME)
            .add(OpenableColumns.SIZE)
            .build();

    private static final int BULK_INSERTS_PER_YIELD_POINT = 50;

    private final String mTableName;
    private final CallLogDatabaseHelper mDbHelper;
    private final Context mContext;
    private final VoicemailTable.DelegateHelper mDelegateHelper;
    private final CallLogInsertionHelper mCallLogInsertionHelper;

    public VoicemailContentTable(String tableName, Context context, CallLogDatabaseHelper dbHelper,
            VoicemailTable.DelegateHelper contentProviderHelper,
            CallLogInsertionHelper callLogInsertionHelper) {
        mTableName = tableName;
        mContext = context;
        mDbHelper = dbHelper;
        mDelegateHelper = contentProviderHelper;
        mVoicemailProjectionMap = new ProjectionMap.Builder()
                .add(Voicemails._ID)
                .add(Voicemails.NUMBER)
                .add(Voicemails.DATE)
                .add(Voicemails.DURATION)
                .add(Voicemails.NEW)
                .add(Voicemails.IS_READ)
                .add(Voicemails.TRANSCRIPTION)
                .add(Voicemails.TRANSCRIPTION_STATE)
                .add(Voicemails.STATE)
                .add(Voicemails.SOURCE_DATA)
                .add(Voicemails.SOURCE_PACKAGE)
                .add(Voicemails.HAS_CONTENT)
                .add(Voicemails.MIME_TYPE)
                .add(Voicemails._DATA)
                .add(Voicemails.PHONE_ACCOUNT_COMPONENT_NAME)
                .add(Voicemails.PHONE_ACCOUNT_ID)
                .add(Voicemails.DIRTY)
                .add(Voicemails.DELETED)
                .add(Voicemails.LAST_MODIFIED)
                .add(Voicemails.BACKED_UP)
                .add(Voicemails.RESTORED)
                .add(Voicemails.ARCHIVED)
                .add(Voicemails.IS_OMTP_VOICEMAIL)
                .add(OpenableColumns.DISPLAY_NAME, createDisplayName(context))
                .add(OpenableColumns.SIZE, "NULL")
                .build();
        mCallLogInsertionHelper = callLogInsertionHelper;
    }

    /**
     * Calculate a suitable value for the display name column.
     * <p>
     * This is a bit of a hack, it uses a suitably localized string and uses SQL to combine this
     * with the number column.
     */
    private static String createDisplayName(Context context) {
        String prefix = context.getString(R.string.voicemail_from_column);
        return DatabaseUtils.sqlEscapeString(prefix) + " || " + Voicemails.NUMBER;
    }

    @Override
    public Uri insert(UriData uriData, ContentValues values) {
        DatabaseModifier modifier = createDatabaseModifier(mDbHelper.getWritableDatabase());
        Uri uri = insertRow(modifier, uriData, values);
        return uri;
    }

    @Override
    public int bulkInsert(UriData uriData, ContentValues[] values) {
        DatabaseModifier modifier = createDatabaseModifier(mDbHelper.getWritableDatabase());
        modifier.startBulkOperation();
        int count = 0;
        for (ContentValues value : values) {
            Uri uri = insertRow(modifier, uriData, value);
            if (uri != null) {
                count++;
            }
            if((count % BULK_INSERTS_PER_YIELD_POINT) == 0){
                modifier.yieldBulkOperation();
            }
        }
        modifier.finishBulkOperation();
        return count;
    }

    private Uri insertRow(DatabaseModifier modifier, UriData uriData, ContentValues values) {
        checkForSupportedColumns(mVoicemailProjectionMap, values);
        ContentValues copiedValues = new ContentValues(values);
        checkInsertSupported(uriData);
        mDelegateHelper.checkAndAddSourcePackageIntoValues(uriData, copiedValues);

        // Add the computed fields to the copied values.
        mCallLogInsertionHelper.addComputedValues(copiedValues);

        // "_data" column is used by base ContentProvider's openFileHelper() to determine filename
        // when Input/Output stream is requested to be opened.
        copiedValues.put(Voicemails._DATA, generateDataFile());

        // call type is always voicemail.
        copiedValues.put(Calls.TYPE, Calls.VOICEMAIL_TYPE);
        // A voicemail is marked as new unless it is marked as read or explicitly overridden.
        boolean isRead = values.containsKey(Calls.IS_READ) ?
                values.getAsBoolean(Calls.IS_READ) : false;
        if (!values.containsKey(Calls.NEW)) {
            copiedValues.put(Calls.NEW, !isRead);
        }

        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        long rowId = modifier.insert(mTableName, null, copiedValues);
        if (rowId > 0) {
            Uri newUri = ContentUris.withAppendedId(uriData.getUri(), rowId);
            // Populate the 'voicemail_uri' field to be used by the call_log provider.
            updateVoicemailUri(db, newUri);
            return newUri;
        }
        return null;
    }

    private void checkInsertSupported(UriData uriData) {
        if (uriData.hasId()) {
            throw new UnsupportedOperationException(String.format(
                    "Cannot insert URI: %s. Inserted URIs should not contain an id.",
                    uriData.getUri()));
        }
    }

    /** Generates a random file for storing audio data. */
    private String generateDataFile() {
        try {
            File dataDirectory = mContext.getDir(DATA_DIRECTORY, Context.MODE_PRIVATE);
            File voicemailFile = File.createTempFile("voicemail", "", dataDirectory);
            return voicemailFile.getAbsolutePath();
        } catch (IOException e) {
            // If we are unable to create a temporary file, something went horribly wrong.
            throw new RuntimeException("unable to create temp file", e);
        }
    }
    private void updateVoicemailUri(SQLiteDatabase db, Uri newUri) {
        ContentValues values = new ContentValues();
        values.put(Calls.VOICEMAIL_URI, newUri.toString());
        // Directly update the db because we cannot update voicemail_uri through external
        // update() due to projectionMap check. This also avoids unnecessary permission
        // checks that are already done as part of insert request.
        db.update(mTableName, values, UriData.createUriData(newUri).getWhereClause(), null);
    }

    @Override
    public int delete(UriData uriData, String selection, String[] selectionArgs) {
        final SQLiteDatabase db = mDbHelper.getWritableDatabase();
        String combinedClause = concatenateClauses(selection, uriData.getWhereClause(),
                getCallTypeClause());

        // Delete all the files associated with this query.  Once we've deleted the rows, there will
        // be no way left to get hold of the files.
        Cursor cursor = null;
        try {
            cursor = query(uriData, FILENAME_ONLY_PROJECTION, selection, selectionArgs, null);
            while (cursor.moveToNext()) {
                String filename = cursor.getString(0);
                if (filename == null) {
                    Log.w(TAG, "No filename for uri " + uriData.getUri() + ", cannot delete file");
                    continue;
                }
                File file = new File(filename);
                if (file.exists()) {
                    boolean success = file.delete();
                    if (!success) {
                        Log.e(TAG, "Failed to delete file: " + file.getAbsolutePath());
                    }
                }
            }
        } finally {
            CloseUtils.closeQuietly(cursor);
        }

        // Now delete the rows themselves.
        return createDatabaseModifier(db).delete(mTableName, combinedClause,
                selectionArgs);
    }

    @Override
    public Cursor query(UriData uriData, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        qb.setTables(mTableName);
        qb.setProjectionMap(mVoicemailProjectionMap);
        qb.setStrict(true);

        String combinedClause = concatenateClauses(selection, uriData.getWhereClause(),
                getCallTypeClause());
        SQLiteDatabase db = mDbHelper.getReadableDatabase();
        Cursor c = qb.query(db, projection, combinedClause, selectionArgs, null, null, sortOrder);
        if (c != null) {
            c.setNotificationUri(mContext.getContentResolver(), Voicemails.CONTENT_URI);
        }
        return c;
    }

    @Override
    public int update(UriData uriData, ContentValues values, String selection,
            String[] selectionArgs) {

        checkForSupportedColumns(ALLOWED_COLUMNS, values, "Updates are not allowed.");
        checkUpdateSupported(uriData);

        final SQLiteDatabase db = mDbHelper.getWritableDatabase();
        // TODO: This implementation does not allow bulk update because it only accepts
        // URI that include message Id. I think we do want to support bulk update.
        String combinedClause = concatenateClauses(selection, uriData.getWhereClause(),
                getCallTypeClause());
        return createDatabaseModifier(db).update(uriData.getUri(), mTableName, values, combinedClause,
                selectionArgs);
    }

    private void checkUpdateSupported(UriData uriData) {
        if (!uriData.hasId()) {
            throw new UnsupportedOperationException(String.format(
                    "Cannot update URI: %s.  Bulk update not supported", uriData.getUri()));
        }
    }

    @Override
    public String getType(UriData uriData) {
        if (uriData.hasId()) {
            return Voicemails.ITEM_TYPE;
        } else {
            return Voicemails.DIR_TYPE;
        }
    }

    @Override
    public ParcelFileDescriptor openFile(UriData uriData, String mode)
            throws FileNotFoundException {
        return mDelegateHelper.openDataFile(uriData, mode);
    }

    @Override
    public ArraySet<String> getSourcePackages() {
        return mDbHelper.selectDistinctColumn(mTableName, Voicemails.SOURCE_PACKAGE);
    }

    /** Creates a clause to restrict the selection to only voicemail call type.*/
    private String getCallTypeClause() {
        return getEqualityClause(Calls.TYPE, Calls.VOICEMAIL_TYPE);
    }

    private DatabaseModifier createDatabaseModifier(SQLiteDatabase db) {
        return new DbModifierWithNotification(mTableName, db, mContext);
    }

}
