/*
 * Copyright (C) 2010 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 android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.util.Log;

import com.android.providers.contacts.aggregation.AbstractContactAggregator;

import java.io.IOException;

/**
 * Handler for photo data rows.
 */
public class DataRowHandlerForPhoto extends DataRowHandler {

    private static final String TAG = "DataRowHandlerForPhoto";

    private final PhotoStore mPhotoStore;
    private final int mMaxDisplayPhotoDim;
    private final int mMaxThumbnailPhotoDim;

    /**
     * If this is set in the ContentValues passed in, it indicates that the caller has
     * already taken care of photo processing, and that the row should be ready for
     * insert/update.  This is used when the photo has been written directly to an
     * asset file.
     */
    /* package */ static final String SKIP_PROCESSING_KEY = "skip_processing";

    public DataRowHandlerForPhoto(
            Context context, ContactsDatabaseHelper dbHelper, AbstractContactAggregator aggregator,
            PhotoStore photoStore, int maxDisplayPhotoDim, int maxThumbnailPhotoDim) {
        super(context, dbHelper, aggregator, Photo.CONTENT_ITEM_TYPE);
        mPhotoStore = photoStore;
        mMaxDisplayPhotoDim = maxDisplayPhotoDim;
        mMaxThumbnailPhotoDim = maxThumbnailPhotoDim;
    }

    @Override
    public long insert(SQLiteDatabase db, TransactionContext txContext, long rawContactId,
            ContentValues values) {

        if (values.containsKey(SKIP_PROCESSING_KEY)) {
            values.remove(SKIP_PROCESSING_KEY);
        } else {
            // Pre-process the photo if one exists.
            if (!preProcessPhoto(values)) {
                return 0;
            }
        }

        long dataId = super.insert(db, txContext, rawContactId, values);
        if (!txContext.isNewRawContact(rawContactId)) {
            mContactAggregator.updatePhotoId(db, rawContactId);
        }
        return dataId;
    }

    @Override
    public boolean update(SQLiteDatabase db, TransactionContext txContext, ContentValues values,
            Cursor c, boolean callerIsSyncAdapter) {
        long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID);

        if (values.containsKey(SKIP_PROCESSING_KEY)) {
            values.remove(SKIP_PROCESSING_KEY);
        } else {
            // Pre-process the photo if one exists.
            if (!preProcessPhoto(values)) {
                return false;
            }
        }

        // Do the actual update.
        if (!super.update(db, txContext, values, c, callerIsSyncAdapter)) {
            return false;
        }

        mContactAggregator.updatePhotoId(db, rawContactId);
        return true;
    }

    /**
     * Pre-processes the given content values for update or insert.  If the photo column contains
     * null or an empty byte array, both that column and the photo file ID will be nulled out.
     * If a photo was specified but could not be processed, this will return false.
     * @param values The content values passed in.
     * @return Whether processing was successful - on failure, the operation should abort.
     */
    private boolean preProcessPhoto(ContentValues values) {
        if (values.containsKey(Photo.PHOTO)) {
            boolean photoExists = hasNonNullPhoto(values);
            if (photoExists) {
                if (!processPhoto(values)) {
                    // A photo was passed in, but we couldn't process it.  Update failed.
                    return false;
                }
            } else {
                // The photo key was passed in, but it was either null or an empty byte[].
                // We should set the photo and photo file ID fields to null for the update.
                values.putNull(Photo.PHOTO);
                values.putNull(Photo.PHOTO_FILE_ID);
            }
        }
        return true;
    }

    private boolean hasNonNullPhoto(ContentValues values) {
        byte[] photoBytes = values.getAsByteArray(Photo.PHOTO);
        return photoBytes != null && photoBytes.length > 0;
    }

    @Override
    public int delete(SQLiteDatabase db, TransactionContext txContext, Cursor c) {
        long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID);
        int count = super.delete(db, txContext, c);
        mContactAggregator.updatePhotoId(db, rawContactId);
        return count;
    }

    /**
     * Reads the photo out of the given values object and processes it, placing the processed
     * photos (a photo store file ID and a compressed thumbnail) back into the ContentValues
     * object.
     * @param values The values being inserted or updated - assumed to contain a photo BLOB.
     * @return Whether an image was successfully decoded and processed.
     */
    private boolean processPhoto(ContentValues values) {
        byte[] originalPhoto = values.getAsByteArray(Photo.PHOTO);
        if (originalPhoto != null) {
            try {
                PhotoProcessor processor = new PhotoProcessor(
                        originalPhoto, mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim);
                long photoFileId = mPhotoStore.insert(processor);
                if (photoFileId != 0) {
                    values.put(Photo.PHOTO_FILE_ID, photoFileId);
                } else {
                    values.putNull(Photo.PHOTO_FILE_ID);
                }
                values.put(Photo.PHOTO, processor.getThumbnailPhotoBytes());
                return true;
            } catch (IOException ioe) {
                Log.e(TAG, "Could not process photo for insert or update", ioe);
            }
        }
        return false;
    }
}
