/*
 * 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 android.app.backup;

import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.os.ParcelFileDescriptor;
import android.util.Slog;
import android.view.Display;
import android.view.WindowManager;

import java.io.File;

/**
 * Helper for backing up / restoring wallpapers.  Basically an AbsoluteFileBackupHelper,
 * but with logic for deciding what to do with restored wallpaper images.
 *
 * @hide
 */
public class WallpaperBackupHelper extends FileBackupHelperBase implements BackupHelper {
    private static final String TAG = "WallpaperBackupHelper";
    private static final boolean DEBUG = true;

    // This path must match what the WallpaperManagerService uses
    private static final String WALLPAPER_IMAGE = "/data/data/com.android.settings/files/wallpaper";

    // Stage file - should be adjacent to the WALLPAPER_IMAGE location.  The wallpapers
    // will be saved to this file from the restore stream, then renamed to the proper
    // location if it's deemed suitable.
    private static final String STAGE_FILE = "/data/data/com.android.settings/files/wallpaper-tmp";

    Context mContext;
    String[] mFiles;
    double mDesiredMinWidth;
    double mDesiredMinHeight;

    /**
     * Construct a helper for backing up / restoring the files at the given absolute locations
     * within the file system.
     *
     * @param context
     * @param files
     */
    public WallpaperBackupHelper(Context context, String... files) {
        super(context);

        mContext = context;
        mFiles = files;

        WallpaperManager wpm;
        wpm = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
        mDesiredMinWidth = (double) wpm.getDesiredMinimumWidth();
        mDesiredMinHeight = (double) wpm.getDesiredMinimumHeight();

        if (mDesiredMinWidth <= 0 || mDesiredMinHeight <= 0) {
            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display d = wm.getDefaultDisplay();
            Point size = new Point();
            d.getSize(size);
            mDesiredMinWidth = size.x;
            mDesiredMinHeight = size.y;
        }

        if (DEBUG) {
            Slog.d(TAG, "dmW=" + mDesiredMinWidth + " dmH=" + mDesiredMinHeight);
        }
    }

    /**
     * Based on oldState, determine which of the files from the application's data directory
     * need to be backed up, write them to the data stream, and fill in newState with the
     * state as it exists now.
     */
    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) {
        performBackup_checked(oldState, data, newState, mFiles, mFiles);
    }

    /**
     * Restore one absolute file entity from the restore stream.  If we're restoring the
     * magic wallpaper file, take specific action to determine whether it is suitable for
     * the current device.
     */
    public void restoreEntity(BackupDataInputStream data) {
        final String key = data.getKey();
        if (isKeyInList(key, mFiles)) {
            if (key.equals(WALLPAPER_IMAGE)) {
                // restore the file to the stage for inspection
                File f = new File(STAGE_FILE);
                if (writeFile(f, data)) {

                    // Preflight the restored image's dimensions without loading it
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true;
                    BitmapFactory.decodeFile(STAGE_FILE, options);

                    if (DEBUG) Slog.d(TAG, "Restoring wallpaper image w=" + options.outWidth
                            + " h=" + options.outHeight);

                    // How much does the image differ from our preference?  The threshold
                    // here is set to accept any image larger than our target, because
                    // scaling down is acceptable; but to reject images that are deemed
                    // "too small" to scale up attractively.  The value 1.33 is just barely
                    // too low to pass Nexus 1 or Droid wallpapers for use on a Xoom, but
                    // will pass anything relatively larger.
                    double widthRatio = mDesiredMinWidth / options.outWidth;
                    double heightRatio = mDesiredMinHeight / options.outHeight;
                    if (widthRatio > 0 && widthRatio < 1.33
                            && heightRatio > 0 && heightRatio < 1.33) {
                        // sufficiently close to our resolution; go ahead and use it
                        if (DEBUG) Slog.d(TAG, "wallpaper dimension match; using");
                        f.renameTo(new File(WALLPAPER_IMAGE));
                        // TODO: spin a service to copy the restored image to sd/usb storage,
                        // since it does not exist anywhere other than the private wallpaper
                        // file.
                    } else {
                        if (DEBUG) Slog.d(TAG, "dimensions too far off: wr=" + widthRatio
                                + " hr=" + heightRatio);
                        f.delete();
                    }
                }
            } else {
                // Some other normal file; just decode it to its destination
                File f = new File(key);
                writeFile(f, data);
            }
        }
    }
}
