// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// 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 dev.cobalt.storage;

import static dev.cobalt.util.Log.TAG;

import android.os.FileObserver;
import android.support.annotation.Nullable;
import com.google.protobuf.InvalidProtocolBufferException;
import dev.cobalt.storage.StorageProto.Storage;
import dev.cobalt.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

/**
 * A class to load Cobalt storage from the file system.
 */
public class CobaltStorageLoader {

  private final File filesDir;
  private final StorageFileObserver fileObserver;

  private static final String STORAGE_NAME_PREFIX = ".starboard";
  private static final String STORAGE_NAME_SUFFIX = ".storage";
  private static final String STORAGE_HEADER = "SAV1";

  /**
   * Initializes the loader with the files directory root.
   *
   * @param filesDir a File object representing the files directory.
   */
  public CobaltStorageLoader(File filesDir) {
    if (filesDir == null) {
      throw new IllegalArgumentException("A valid filesDir object is required");
    }
    this.filesDir = filesDir;
    this.fileObserver = StorageFileObserver.create(filesDir);
  }

  /**
   * Reads synchronously the Cobalt storage from the file system.
   *
   * @return a snapshot of the Cobalt storage as a proto message.
   */
  public Storage loadStorageSnapshot() {
    String fileName = getStorageFileName();
    if (fileName == null) {
      return Storage.getDefaultInstance();
    }
    Storage storage = loadStorageFile(new File(filesDir, fileName));
    return (storage != null) ? storage : Storage.getDefaultInstance();
  }

  @Nullable
  private static Storage loadStorageFile(File file) {
    byte[] storageBlob = getStorageBlob(file);
    if (storageBlob == null) {
      Log.e(TAG, "Failed to get storage blob");
      return null;
    }
    if (!validateStorageBlob(storageBlob)) {
      Log.e(TAG, "Invalid storage blob");
      return null;
    }
    storageBlob = Arrays.copyOfRange(storageBlob, STORAGE_HEADER.length(), storageBlob.length);
    try {
      return Storage.parseFrom(storageBlob);
    } catch (InvalidProtocolBufferException e) {
      Log.e(TAG, "Failed parsing the blob", e);
    }
    return null;
  }

  private static boolean validateStorageBlob(byte[] storageBlob) {
    if (storageBlob == null || storageBlob.length < STORAGE_HEADER.length()) {
      return false;
    }
    String header = new String(storageBlob, 0, STORAGE_HEADER.length());
    return header.equals(STORAGE_HEADER);
  }

  @Nullable
  private static byte[] getStorageBlob(File file) {
    try (FileInputStream in = new FileInputStream(file);
        ByteArrayOutputStream out = new ByteArrayOutputStream()) {
      byte[] buffer = new byte[8192];
      int len;
      while ((len = in.read(buffer)) != -1) {
        out.write(buffer, 0, len);
      }
      return out.toByteArray();
    } catch (IOException e) {
      Log.e(TAG, "Failed to read storage blob", e);
    }
    return null;
  }

  @Nullable
  private String getStorageFileName() {
    String[] fileNames = filesDir.list();
    if (fileNames == null) {
      Log.w(TAG, "Empty file list");
      return null;
    }
    for (String fileName : fileNames) {
      if (isStorageFile(fileName)) {
        File storageFile = new File(filesDir, fileName);
        if (storageFile.length() > 0) {
          return fileName;
        }
      }
    }
    Log.w(TAG, "Failed to find storage file name");
    return null;
  }

  private static boolean isStorageFile(String fileName) {
    return fileName != null
        && fileName.startsWith(STORAGE_NAME_PREFIX)
        && fileName.endsWith(STORAGE_NAME_SUFFIX);
  }

  /**
   * Set the observer to be notified when storage changes.
   *
   * @param storageObserver will be called when storage changes.
   */
  public void setObserver(@Nullable CobaltStorageObserver storageObserver) {
    fileObserver.setStorageObserver(storageObserver);
  }

  /**
   * Observer that is called when Cobalt storage changes.
   */
  public interface CobaltStorageObserver {

    /**
     * Called when Cobalt storage changes.
     *
     * <p>This method is invoked on a special thread. It runs independently of any threads, so take
     * care to use appropriate synchronization! Consider using Handler#post(Runnable) to shift event
     * handling work to the main thread to avoid concurrency problems.
     *
     * @param snapshot the Cobalt storage as a proto message.
     */
    void onCobaltStorageChanged(Storage snapshot);
  }

  private static class StorageFileObserver extends FileObserver {

    private final File filesDir;
    private CobaltStorageObserver storageObserver = null;

    static StorageFileObserver create(File filesDir) {
      return new StorageFileObserver(filesDir.getAbsolutePath());
    }

    StorageFileObserver(String filesDirPath) {
      super(filesDirPath, MOVED_TO);
      this.filesDir = new File(filesDirPath);
    }

    void setStorageObserver(@Nullable CobaltStorageObserver storageObserver) {
      if (this.storageObserver != null) {
        stopWatching();
      }
      this.storageObserver = storageObserver;
      if (this.storageObserver != null) {
        startWatching();
      }
    }

    @Override
    public void onEvent(int event, @Nullable String fileName) {
      // Expect a MOVED_TO event since SbStorageWrite() creates a temp file then moves it in place.
      if (event != MOVED_TO || storageObserver == null || !isStorageFile(fileName)) {
        return;
      }
      Storage storage = loadStorageFile(new File(filesDir, fileName));
      if (storage != null) {
        storageObserver.onCobaltStorageChanged(storage);
      }
    }
  }
}
