/*
 * Copyright (C) 2015 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.os.ParcelFileDescriptor;
import android.util.ArrayMap;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.CRC32;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;

/**
 * Utility class for writing BackupHelpers whose underlying data is a
 * fixed set of byte-array blobs.  The helper manages diff detection
 * and compression on the wire.
 *
 * @hide
 */
public abstract class BlobBackupHelper implements BackupHelper {
    private static final String TAG = "BlobBackupHelper";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private final int mCurrentBlobVersion;
    private final String[] mKeys;

    public BlobBackupHelper(int currentBlobVersion, String... keys) {
        mCurrentBlobVersion = currentBlobVersion;
        mKeys = keys;
    }

    // Client interface

    /**
     * Generate and return the byte array containing the backup payload describing
     * the current data state.  During a backup operation this method is called once
     * per key that was supplied to the helper's constructor.
     *
     * @return A byte array containing the data blob that the caller wishes to store,
     *     or {@code null} if the current state is empty or undefined.
     */
    abstract protected byte[] getBackupPayload(String key);

    /**
     * Given a byte array that was restored from backup, do whatever is appropriate
     * to apply that described state in the live system.  This method is called once
     * per key/value payload that was delivered for restore.  Typically data is delivered
     * for restore in lexical order by key, <i>not</i> in the order in which the keys
     * were supplied in the constructor.
     *
     * @param payload The byte array that was passed to {@link #getBackupPayload()}
     *     on the ancestral device.
     */
    abstract protected void applyRestoredPayload(String key, byte[] payload);


    // Internal implementation

    /*
     * State on-disk format:
     * [Int]    : overall blob version number
     * [Int=N] : number of keys represented in the state blob
     * N* :
     *     [String] key
     *     [Long]   blob checksum, calculated after compression
     */
    @SuppressWarnings("resource")
    private ArrayMap<String, Long> readOldState(ParcelFileDescriptor oldStateFd) {
        final ArrayMap<String, Long> state = new ArrayMap<String, Long>();

        FileInputStream fis = new FileInputStream(oldStateFd.getFileDescriptor());
        BufferedInputStream bis = new BufferedInputStream(fis);
        DataInputStream in = new DataInputStream(bis);

        try {
            int version = in.readInt();
            if (version <= mCurrentBlobVersion) {
                final int numKeys = in.readInt();
                for (int i = 0; i < numKeys; i++) {
                    String key = in.readUTF();
                    long checksum = in.readLong();
                    state.put(key, checksum);
                }
            } else {
                Log.w(TAG, "Prior state from unrecognized version " + version);
            }
        } catch (EOFException e) {
            // Empty file is expected on first backup,  so carry on. If the state
            // is truncated we just treat it the same way.
            state.clear();
        } catch (Exception e) {
            Log.e(TAG, "Error examining prior backup state " + e.getMessage());
            state.clear();
        }

        return state;
    }

    /**
     * New overall state record
     */
    private void writeBackupState(ArrayMap<String, Long> state, ParcelFileDescriptor stateFile) {
        try {
            FileOutputStream fos = new FileOutputStream(stateFile.getFileDescriptor());

            // We explicitly don't close 'out' because we must not close the backing fd.
            // The FileOutputStream will not close it implicitly.
            @SuppressWarnings("resource")
            DataOutputStream out = new DataOutputStream(fos);

            out.writeInt(mCurrentBlobVersion);

            final int N = (state != null) ? state.size() : 0;
            out.writeInt(N);
            for (int i = 0; i < N; i++) {
                out.writeUTF(state.keyAt(i));
                out.writeLong(state.valueAt(i).longValue());
            }
        } catch (IOException e) {
            Log.e(TAG, "Unable to write updated state", e);
        }
    }

    // Also versions the deflated blob internally in case we need to revise it
    private byte[] deflate(byte[] data) {
        byte[] result = null;
        if (data != null) {
            try {
                ByteArrayOutputStream sink = new ByteArrayOutputStream();
                DataOutputStream headerOut = new DataOutputStream(sink);

                // write the header directly to the sink ahead of the deflated payload
                headerOut.writeInt(mCurrentBlobVersion);

                DeflaterOutputStream out = new DeflaterOutputStream(sink);
                out.write(data);
                out.close();  // finishes and commits the compression run
                result = sink.toByteArray();
                if (DEBUG) {
                    Log.v(TAG, "Deflated " + data.length + " bytes to " + result.length);
                }
            } catch (IOException e) {
                Log.w(TAG, "Unable to process payload: " + e.getMessage());
            }
        }
        return result;
    }

    // Returns null if inflation failed
    private byte[] inflate(byte[] compressedData) {
        byte[] result = null;
        if (compressedData != null) {
            try {
                ByteArrayInputStream source = new ByteArrayInputStream(compressedData);
                DataInputStream headerIn = new DataInputStream(source);
                int version = headerIn.readInt();
                if (version > mCurrentBlobVersion) {
                    Log.w(TAG, "Saved payload from unrecognized version " + version);
                    return null;
                }

                InflaterInputStream in = new InflaterInputStream(source);
                ByteArrayOutputStream inflated = new ByteArrayOutputStream();
                byte[] buffer = new byte[4096];
                int nRead;
                while ((nRead = in.read(buffer)) > 0) {
                    inflated.write(buffer, 0, nRead);
                }
                in.close();
                inflated.flush();
                result = inflated.toByteArray();
                if (DEBUG) {
                    Log.v(TAG, "Inflated " + compressedData.length + " bytes to " + result.length);
                }
            } catch (IOException e) {
                // result is still null here
                Log.w(TAG, "Unable to process restored payload: " + e.getMessage());
            }
        }
        return result;
    }

    private long checksum(byte[] buffer) {
        if (buffer != null) {
            try {
                CRC32 crc = new CRC32();
                ByteArrayInputStream bis = new ByteArrayInputStream(buffer);
                byte[] buf = new byte[4096];
                int nRead = 0;
                while ((nRead = bis.read(buf)) >= 0) {
                    crc.update(buf, 0, nRead);
                }
                return crc.getValue();
            } catch (Exception e) {
                // whoops; fall through with an explicitly bogus checksum
            }
        }
        return -1;
    }

    // BackupHelper interface

    @Override
    public void performBackup(ParcelFileDescriptor oldStateFd, BackupDataOutput data,
            ParcelFileDescriptor newStateFd) {

        final ArrayMap<String, Long> oldState = readOldState(oldStateFd);
        final ArrayMap<String, Long> newState = new ArrayMap<String, Long>();

        try {
            for (String key : mKeys) {
                final byte[] payload = deflate(getBackupPayload(key));
                final long checksum = checksum(payload);
                newState.put(key, checksum);

                Long oldChecksum = oldState.get(key);
                if (oldChecksum == null || checksum != oldChecksum) {
                    if (DEBUG) {
                        Log.i(TAG, "State has changed for key " + key + ", writing");
                    }
                    if (payload != null) {
                        data.writeEntityHeader(key, payload.length);
                        data.writeEntityData(payload, payload.length);
                    } else {
                        // state's changed but there's no current payload => delete
                        data.writeEntityHeader(key, -1);
                    }
                } else {
                    if (DEBUG) {
                        Log.i(TAG, "No change under key " + key + " => not writing");
                    }
                }
            }
        } catch (Exception e) {
            Log.w(TAG,  "Unable to record notification state: " + e.getMessage());
            newState.clear();
        } finally {
            // Always recommit the state even if nothing changed
            writeBackupState(newState, newStateFd);
        }
    }

    @Override
    public void restoreEntity(BackupDataInputStream data) {
        final String key = data.getKey();
        try {
            // known key?
            int which;
            for (which = 0; which < mKeys.length; which++) {
                if (key.equals(mKeys[which])) {
                    break;
                }
            }
            if (which >= mKeys.length) {
                Log.e(TAG, "Unrecognized key " + key + ", ignoring");
                return;
            }

            byte[] compressed = new byte[data.size()];
            data.read(compressed);
            byte[] payload = inflate(compressed);
            applyRestoredPayload(key, payload);
        } catch (Exception e) {
            Log.e(TAG, "Exception restoring entity " + key + " : " + e.getMessage());
        }
    }

    @Override
    public void writeNewStateDescription(ParcelFileDescriptor newState) {
        // Just ensure that we do a full backup the first time after a restore
        writeBackupState(null, newState);
    }
}
