/*
 * Copyright (C) 2020 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.google.android.connecteddevice.storage;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static org.junit.Assert.assertThrows;

import androidx.room.Room;
import android.content.Context;
import android.util.Base64;
import android.util.Pair;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.connecteddevice.model.AssociatedDevice;
import com.google.android.connecteddevice.util.ByteUtils;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public final class ConnectedDeviceStorageTest {
  private static final int ACTIVE_USER_ID = 10;

  private final Context context = ApplicationProvider.getApplicationContext();

  private ConnectedDeviceStorage connectedDeviceStorage;

  private List<Pair<Integer, AssociatedDevice>> addedAssociatedDevices;

  @Before
  public void setUp() {
    AssociatedDeviceDao database =
        Room.inMemoryDatabaseBuilder(context, ConnectedDeviceDatabase.class)
            .allowMainThreadQueries()
            .setQueryExecutor(directExecutor())
            .build()
            .associatedDeviceDao();

    connectedDeviceStorage = new ConnectedDeviceStorage(context, new FakeCryptoHelper(), database);
    addedAssociatedDevices = new ArrayList<>();
  }

  @After
  public void tearDown() {
    // Clear any associated devices added during tests.
    for (Pair<Integer, AssociatedDevice> device : addedAssociatedDevices) {
      connectedDeviceStorage.removeAssociatedDevice(device.first, device.second.getDeviceId());
    }
  }

  @Test
  public void getAssociatedDeviceIdsForUser_includesNewlyAddedDevice() {
    AssociatedDevice addedDevice = addRandomAssociatedDevice(ACTIVE_USER_ID);
    List<String> associatedDevices =
        connectedDeviceStorage.getAssociatedDeviceIdsForUser(ACTIVE_USER_ID);
    assertThat(associatedDevices).containsExactly(addedDevice.getDeviceId());
  }

  @Test
  public void getAssociatedDeviceIdsForUser_excludesDeviceAddedForOtherUser() {
    addRandomAssociatedDevice(ACTIVE_USER_ID);
    List<String> associatedDevices =
        connectedDeviceStorage.getAssociatedDeviceIdsForUser(ACTIVE_USER_ID + 1);
    assertThat(associatedDevices).isEmpty();
  }

  @Test
  public void getAssociatedDeviceIdsForUser_excludesRemovedDevice() {
    AssociatedDevice addedDevice = addRandomAssociatedDevice(ACTIVE_USER_ID);
    connectedDeviceStorage.removeAssociatedDevice(ACTIVE_USER_ID, addedDevice.getDeviceId());
    List<String> associatedDevices =
        connectedDeviceStorage.getAssociatedDeviceIdsForUser(ACTIVE_USER_ID);
    assertThat(associatedDevices).isEmpty();
  }

  @Test
  public void getAssociatedDevicesForUser_includesNewlyAddedDevice() {
    AssociatedDevice addedDevice = addRandomAssociatedDevice(ACTIVE_USER_ID);
    List<AssociatedDevice> associatedDevices =
        connectedDeviceStorage.getAssociatedDevicesForUser(ACTIVE_USER_ID);
    assertThat(associatedDevices).containsExactly(addedDevice);
  }

  @Test
  public void getAssociatedDevicesForUser_excludesDeviceAddedForOtherUser() {
    addRandomAssociatedDevice(ACTIVE_USER_ID);
    List<String> associatedDevices =
        connectedDeviceStorage.getAssociatedDeviceIdsForUser(ACTIVE_USER_ID + 1);
    assertThat(associatedDevices).isEmpty();
  }

  @Test
  public void getAssociatedDevicesForUser_excludesRemovedDevice() {
    AssociatedDevice addedDevice = addRandomAssociatedDevice(ACTIVE_USER_ID);
    connectedDeviceStorage.removeAssociatedDevice(ACTIVE_USER_ID, addedDevice.getDeviceId());
    List<AssociatedDevice> associatedDevices =
        connectedDeviceStorage.getAssociatedDevicesForUser(ACTIVE_USER_ID);
    assertThat(associatedDevices).isEmpty();
  }

  @Test
  public void getEncryptionKey_returnsSavedKey() {
    String deviceId = addRandomAssociatedDevice(ACTIVE_USER_ID).getDeviceId();
    byte[] key = ByteUtils.randomBytes(16);
    connectedDeviceStorage.saveEncryptionKey(deviceId, key);
    assertThat(connectedDeviceStorage.getEncryptionKey(deviceId)).isEqualTo(key);
  }

  @Test
  public void getEncryptionKey_returnsNullForUnrecognizedDeviceId() {
    String deviceId = addRandomAssociatedDevice(ACTIVE_USER_ID).getDeviceId();
    connectedDeviceStorage.saveEncryptionKey(deviceId, ByteUtils.randomBytes(16));
    assertThat(connectedDeviceStorage.getEncryptionKey(UUID.randomUUID().toString())).isNull();
  }

  @Test
  public void saveChallengeSecret_throwsForInvalidLengthSecret() {
    byte[] invalidSecret = ByteUtils.randomBytes(ConnectedDeviceStorage.CHALLENGE_SECRET_BYTES - 1);
    assertThrows(
        InvalidParameterException.class,
        () ->
            connectedDeviceStorage.saveChallengeSecret(
                UUID.randomUUID().toString(), invalidSecret));
  }

  private AssociatedDevice addRandomAssociatedDevice(int userId) {
    AssociatedDevice device =
        new AssociatedDevice(
            UUID.randomUUID().toString(),
            "00:00:00:00:00:00",
            "Test Device",
            /* isConnectionEnabled= */ true);
    addAssociatedDevice(userId, device, ByteUtils.randomBytes(16));
    return device;
  }

  private void addAssociatedDevice(int userId, AssociatedDevice device, byte[] encryptionKey) {
    connectedDeviceStorage.addAssociatedDeviceForUser(userId, device);
    connectedDeviceStorage.saveEncryptionKey(device.getDeviceId(), encryptionKey);
    addedAssociatedDevices.add(new Pair<>(userId, device));
  }

  /** A {@link CryptoHelper} that does base64 de/encoding to simulate encryption. */
  private static class FakeCryptoHelper implements CryptoHelper {
    @Override
    public String encrypt(byte[] value) {
      return Base64.encodeToString(value, Base64.DEFAULT);
    }

    @Override
    public byte[] decrypt(String value) {
      return Base64.decode(value, Base64.DEFAULT);
    }
  }
}
