/*
 * 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 com.android.calllogbackup;

import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.Settings;
import android.telecom.PhoneAccountHandle;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Call log backup agent.
 */
public class CallLogBackupAgent extends BackupAgent {

    @VisibleForTesting
    static class CallLogBackupState {
        int version;
        SortedSet<Integer> callIds;
    }

    @VisibleForTesting
    static class Call {
        int id;
        long date;
        long duration;
        String number;
        int type;
        int numberPresentation;
        String accountComponentName;
        String accountId;
        String accountAddress;
        Long dataUsage;
        int features;

        @Override
        public String toString() {
            if (isDebug()) {
                return  "[" + id + ", account: [" + accountComponentName + " : " + accountId +
                    "]," + number + ", " + date + "]";
            } else {
                return "[" + id + "]";
            }
        }
    }

    static class OEMData {
        String namespace;
        byte[] bytes;

        public OEMData(String namespace, byte[] bytes) {
            this.namespace = namespace;
            this.bytes = bytes == null ? ZERO_BYTE_ARRAY : bytes;
        }
    }

    private static final String TAG = "CallLogBackupAgent";

    private static final String USER_FULL_DATA_BACKUP_AWARE = "user_full_data_backup_aware";

    /** Current version of CallLogBackup. Used to track the backup format. */
    @VisibleForTesting
    static final int VERSION = 1002;
    /** Version indicating that there exists no previous backup entry. */
    @VisibleForTesting
    static final int VERSION_NO_PREVIOUS_STATE = 0;

    static final String NO_OEM_NAMESPACE = "no-oem-namespace";

    static final byte[] ZERO_BYTE_ARRAY = new byte[0];

    static final int END_OEM_DATA_MARKER = 0x60061E;


    private static final String[] CALL_LOG_PROJECTION = new String[] {
        CallLog.Calls._ID,
        CallLog.Calls.DATE,
        CallLog.Calls.DURATION,
        CallLog.Calls.NUMBER,
        CallLog.Calls.TYPE,
        CallLog.Calls.COUNTRY_ISO,
        CallLog.Calls.GEOCODED_LOCATION,
        CallLog.Calls.NUMBER_PRESENTATION,
        CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME,
        CallLog.Calls.PHONE_ACCOUNT_ID,
        CallLog.Calls.PHONE_ACCOUNT_ADDRESS,
        CallLog.Calls.DATA_USAGE,
        CallLog.Calls.FEATURES
    };

    /** ${inheritDoc} */
    @Override
    public void onBackup(ParcelFileDescriptor oldStateDescriptor, BackupDataOutput data,
            ParcelFileDescriptor newStateDescriptor) throws IOException {

        if (shouldPreventBackup(this)) {
            if (isDebug()) {
                Log.d(TAG, "Skipping onBackup");
            }
            return;
        }

        // Get the list of the previous calls IDs which were backed up.
        DataInputStream dataInput = new DataInputStream(
                new FileInputStream(oldStateDescriptor.getFileDescriptor()));
        final CallLogBackupState state;
        try {
            state = readState(dataInput);
        } finally {
            dataInput.close();
        }

        // Run the actual backup of data
        runBackup(state, data, getAllCallLogEntries());

        // Rewrite the backup state.
        DataOutputStream dataOutput = new DataOutputStream(new BufferedOutputStream(
                new FileOutputStream(newStateDescriptor.getFileDescriptor())));
        try {
            writeState(dataOutput, state);
        } finally {
            dataOutput.close();
        }
    }

    /** ${inheritDoc} */
    @Override
    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
            throws IOException {
        if (shouldPreventBackup(this)) {
            if (isDebug()) {
                Log.d(TAG, "Skipping restore");
            }
            return;
        }

        if (isDebug()) {
            Log.d(TAG, "Performing Restore");
        }

        while (data.readNextHeader()) {
            Call call = readCallFromData(data);
            if (call != null) {
                writeCallToProvider(call);
                if (isDebug()) {
                    Log.d(TAG, "Restored call: " + call);
                }
            }
        }
    }

    @VisibleForTesting
    void runBackup(CallLogBackupState state, BackupDataOutput data, Iterable<Call> calls) {
        SortedSet<Integer> callsToRemove = new TreeSet<>(state.callIds);

        // Loop through all the call log entries to identify:
        // (1) new calls
        // (2) calls which have been deleted.
        for (Call call : calls) {
            if (!state.callIds.contains(call.id)) {

                if (isDebug()) {
                    Log.d(TAG, "Adding call to backup: " + call);
                }

                // This call new (not in our list from the last backup), lets back it up.
                addCallToBackup(data, call);
                state.callIds.add(call.id);
            } else {
                // This call still exists in the current call log so delete it from the
                // "callsToRemove" set since we want to keep it.
                callsToRemove.remove(call.id);
            }
        }

        // Remove calls which no longer exist in the set.
        for (Integer i : callsToRemove) {
            if (isDebug()) {
                Log.d(TAG, "Removing call from backup: " + i);
            }

            removeCallFromBackup(data, i);
            state.callIds.remove(i);
        }
    }

    private Iterable<Call> getAllCallLogEntries() {
        List<Call> calls = new LinkedList<>();

        // We use the API here instead of querying ContactsDatabaseHelper directly because
        // CallLogProvider has special locks in place for sychronizing when to read.  Using the APIs
        // gives us that for free.
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(
                CallLog.Calls.CONTENT_URI, CALL_LOG_PROJECTION, null, null, null);
        if (cursor != null) {
            try {
                while (cursor.moveToNext()) {
                    Call call = readCallFromCursor(cursor);
                    if (call != null) {
                        calls.add(call);
                    }
                }
            } finally {
                cursor.close();
            }
        }

        return calls;
    }

    private void writeCallToProvider(Call call) {
        Long dataUsage = call.dataUsage == 0 ? null : call.dataUsage;

        PhoneAccountHandle handle = null;
        if (call.accountComponentName != null && call.accountId != null) {
            handle = new PhoneAccountHandle(
                    ComponentName.unflattenFromString(call.accountComponentName), call.accountId);
        }
        Calls.addCall(null /* CallerInfo */, this, call.number, call.numberPresentation, call.type,
                call.features, handle, call.date, (int) call.duration,
                dataUsage, true /* addForAllUsers */, true /* is_read */);
    }

    @VisibleForTesting
    CallLogBackupState readState(DataInput dataInput) throws IOException {
        CallLogBackupState state = new CallLogBackupState();
        state.callIds = new TreeSet<>();

        try {
            // Read the version.
            state.version = dataInput.readInt();

            if (state.version >= 1) {
                // Read the size.
                int size = dataInput.readInt();

                // Read all of the call IDs.
                for (int i = 0; i < size; i++) {
                    state.callIds.add(dataInput.readInt());
                }
            }
        } catch (EOFException e) {
            state.version = VERSION_NO_PREVIOUS_STATE;
        }

        return state;
    }

    @VisibleForTesting
    void writeState(DataOutput dataOutput, CallLogBackupState state)
            throws IOException {
        // Write version first of all
        dataOutput.writeInt(VERSION);

        // [Version 1]
        // size + callIds
        dataOutput.writeInt(state.callIds.size());
        for (Integer i : state.callIds) {
            dataOutput.writeInt(i);
        }
    }

    @VisibleForTesting
    Call readCallFromData(BackupDataInput data) {
        final int callId;
        try {
            callId = Integer.parseInt(data.getKey());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Unexpected key found in restore: " + data.getKey());
            return null;
        }

        try {
            byte [] byteArray = new byte[data.getDataSize()];
            data.readEntityData(byteArray, 0, byteArray.length);
            DataInputStream dataInput = new DataInputStream(new ByteArrayInputStream(byteArray));

            Call call = new Call();
            call.id = callId;

            int version = dataInput.readInt();
            if (version >= 1) {
                call.date = dataInput.readLong();
                call.duration = dataInput.readLong();
                call.number = readString(dataInput);
                call.type = dataInput.readInt();
                call.numberPresentation = dataInput.readInt();
                call.accountComponentName = readString(dataInput);
                call.accountId = readString(dataInput);
                call.accountAddress = readString(dataInput);
                call.dataUsage = dataInput.readLong();
                call.features = dataInput.readInt();
            }

            if (version >= 1002) {
                String namespace = dataInput.readUTF();
                int length = dataInput.readInt();
                byte[] buffer = new byte[length];
                dataInput.read(buffer);
                readOEMDataForCall(call, new OEMData(namespace, buffer));

                int marker = dataInput.readInt();
                if (marker != END_OEM_DATA_MARKER) {
                    Log.e(TAG, "Did not find END-OEM marker for call " + call.id);
                    // The marker does not match the expected value, ignore this call completely.
                    return null;
                }
            }

            return call;
        } catch (IOException e) {
            Log.e(TAG, "Error reading call data for " + callId, e);
            return null;
        }
    }

    private Call readCallFromCursor(Cursor cursor) {
        Call call = new Call();
        call.id = cursor.getInt(cursor.getColumnIndex(CallLog.Calls._ID));
        call.date = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE));
        call.duration = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DURATION));
        call.number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
        call.type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
        call.numberPresentation =
                cursor.getInt(cursor.getColumnIndex(CallLog.Calls.NUMBER_PRESENTATION));
        call.accountComponentName =
                cursor.getString(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME));
        call.accountId =
                cursor.getString(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID));
        call.accountAddress =
                cursor.getString(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ADDRESS));
        call.dataUsage = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATA_USAGE));
        call.features = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.FEATURES));
        return call;
    }

    private void addCallToBackup(BackupDataOutput output, Call call) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream data = new DataOutputStream(baos);

        try {
            data.writeInt(VERSION);
            data.writeLong(call.date);
            data.writeLong(call.duration);
            writeString(data, call.number);
            data.writeInt(call.type);
            data.writeInt(call.numberPresentation);
            writeString(data, call.accountComponentName);
            writeString(data, call.accountId);
            writeString(data, call.accountAddress);
            data.writeLong(call.dataUsage == null ? 0 : call.dataUsage);
            data.writeInt(call.features);

            OEMData oemData = getOEMDataForCall(call);
            data.writeUTF(oemData.namespace);
            data.writeInt(oemData.bytes.length);
            data.write(oemData.bytes);
            data.writeInt(END_OEM_DATA_MARKER);

            data.flush();

            output.writeEntityHeader(Integer.toString(call.id), baos.size());
            output.writeEntityData(baos.toByteArray(), baos.size());

            if (isDebug()) {
                Log.d(TAG, "Wrote call to backup: " + call + " with byte array: " + baos);
            }
        } catch (IOException e) {
            Log.e(TAG, "Failed to backup call: " + call, e);
        }
    }

    /**
     * Allows OEMs to provide proprietary data to backup along with the rest of the call log
     * data. Because there is no way to provide a Backup Transport implementation
     * nor peek into the data format of backup entries without system-level permissions, it is
     * not possible (at the time of this writing) to write CTS tests for this piece of code.
     * It is, therefore, important that if you alter this portion of code that you
     * test backup and restore of call log is working as expected; ideally this would be tested by
     * backing up and restoring between two different Android phone devices running M+.
     */
    private OEMData getOEMDataForCall(Call call) {
        return new OEMData(NO_OEM_NAMESPACE, ZERO_BYTE_ARRAY);

        // OEMs that want to add their own proprietary data to call log backup should replace the
        // code above with their own namespace and add any additional data they need.
        // Versioning and size-prefixing the data should be done here as needed.
        //
        // Example:

        /*
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream data = new DataOutputStream(baos);

        String customData1 = "Generic OEM";
        int customData2 = 42;

        // Write a version for the data
        data.writeInt(OEM_DATA_VERSION);

        // Write the data and flush
        data.writeUTF(customData1);
        data.writeInt(customData2);
        data.flush();

        String oemNamespace = "com.oem.namespace";
        return new OEMData(oemNamespace, baos.toByteArray());
        */
    }

    /**
     * Allows OEMs to read their own proprietary data when doing a call log restore. It is important
     * that the implementation verify the namespace of the data matches their expected value before
     * attempting to read the data or else you may risk reading invalid data.
     *
     * See {@link #getOEMDataForCall} for information concerning proper testing of this code.
     */
    private void readOEMDataForCall(Call call, OEMData oemData) {
        // OEMs that want to read proprietary data from a call log restore should do so here.
        // Before reading from the data, an OEM should verify that the data matches their
        // expected namespace.
        //
        // Example:

        /*
        if ("com.oem.expected.namespace".equals(oemData.namespace)) {
            ByteArrayInputStream bais = new ByteArrayInputStream(oemData.bytes);
            DataInputStream data = new DataInputStream(bais);

            // Check against this version as we read data.
            int version = data.readInt();
            String customData1 = data.readUTF();
            int customData2 = data.readInt();
            // do something with data
        }
        */
    }


    private void writeString(DataOutputStream data, String str) throws IOException {
        if (str == null) {
            data.writeBoolean(false);
        } else {
            data.writeBoolean(true);
            data.writeUTF(str);
        }
    }

    private String readString(DataInputStream data) throws IOException {
        if (data.readBoolean()) {
            return data.readUTF();
        } else {
            return null;
        }
    }

    private void removeCallFromBackup(BackupDataOutput output, int callId) {
        try {
            output.writeEntityHeader(Integer.toString(callId), -1);
        } catch (IOException e) {
            Log.e(TAG, "Failed to remove call: " + callId, e);
        }
    }

    static boolean shouldPreventBackup(Context context) {
        // Check to see that the user is full-data aware before performing calllog backup.
        return Settings.Secure.getInt(
                context.getContentResolver(), USER_FULL_DATA_BACKUP_AWARE, 0) == 0;
    }

    private static boolean isDebug() {
        return Log.isLoggable(TAG, Log.DEBUG);
    }
}
