//
// Copyright (C) 2012 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.
//

#ifndef UPDATE_ENGINE_COMMON_PREFS_H_
#define UPDATE_ENGINE_COMMON_PREFS_H_

#include <map>
#include <string>
#include <vector>

#include <base/files/file_path.h>

#include "gtest/gtest_prod.h"  // for FRIEND_TEST
#include "update_engine/common/prefs_interface.h"

namespace chromeos_update_engine {

// Implements a preference store by storing the value associated with a key
// in a given storage passed during construction.
class PrefsBase : public PrefsInterface {
 public:
  // Storage interface used to set and retrieve keys.
  class StorageInterface {
   public:
    StorageInterface() = default;
    virtual ~StorageInterface() = default;

    // Get the key named |key| and store its value in the referenced |value|.
    // Returns whether the operation succeeded.
    virtual bool GetKey(const std::string& key, std::string* value) const = 0;

    // Get the keys stored within the namespace. If there are no keys in the
    // namespace, |keys| will be empty. Returns whether the operation succeeded.
    virtual bool GetSubKeys(const std::string& ns,
                            std::vector<std::string>* keys) const = 0;

    // Set the value of the key named |key| to |value| regardless of the
    // previous value. Returns whether the operation succeeded.
    virtual bool SetKey(const std::string& key, const std::string& value) = 0;

    // Returns whether the key named |key| exists.
    virtual bool KeyExists(const std::string& key) const = 0;

    // Deletes the value associated with the key name |key|. Returns whether the
    // key was deleted.
    virtual bool DeleteKey(const std::string& key) = 0;

   private:
    DISALLOW_COPY_AND_ASSIGN(StorageInterface);
  };

  explicit PrefsBase(StorageInterface* storage) : storage_(storage) {}

  // PrefsInterface methods.
  bool GetString(const std::string& key, std::string* value) const override;
  bool SetString(const std::string& key, const std::string& value) override;
  bool GetInt64(const std::string& key, int64_t* value) const override;
  bool SetInt64(const std::string& key, const int64_t value) override;
  bool GetBoolean(const std::string& key, bool* value) const override;
  bool SetBoolean(const std::string& key, const bool value) override;

  bool Exists(const std::string& key) const override;
  bool Delete(const std::string& key) override;

  bool GetSubKeys(const std::string& ns,
                  std::vector<std::string>* keys) const override;

  void AddObserver(const std::string& key,
                   ObserverInterface* observer) override;
  void RemoveObserver(const std::string& key,
                      ObserverInterface* observer) override;

 private:
  // The registered observers watching for changes.
  std::map<std::string, std::vector<ObserverInterface*>> observers_;

  // The concrete implementation of the storage used for the keys.
  StorageInterface* storage_;

  DISALLOW_COPY_AND_ASSIGN(PrefsBase);
};

// Implements a preference store by storing the value associated with
// a key in a separate file named after the key under a preference
// store directory.

class Prefs : public PrefsBase {
 public:
  Prefs() : PrefsBase(&file_storage_) {}

  // Initializes the store by associating this object with |prefs_dir|
  // as the preference store directory. Returns true on success, false
  // otherwise.
  bool Init(const base::FilePath& prefs_dir);

 private:
  FRIEND_TEST(PrefsTest, GetFileNameForKey);
  FRIEND_TEST(PrefsTest, GetFileNameForKeyBadCharacter);
  FRIEND_TEST(PrefsTest, GetFileNameForKeyEmpty);

  class FileStorage : public PrefsBase::StorageInterface {
   public:
    FileStorage() = default;

    bool Init(const base::FilePath& prefs_dir);

    // PrefsBase::StorageInterface overrides.
    bool GetKey(const std::string& key, std::string* value) const override;
    bool GetSubKeys(const std::string& ns,
                    std::vector<std::string>* keys) const override;
    bool SetKey(const std::string& key, const std::string& value) override;
    bool KeyExists(const std::string& key) const override;
    bool DeleteKey(const std::string& key) override;

   private:
    FRIEND_TEST(PrefsTest, GetFileNameForKey);
    FRIEND_TEST(PrefsTest, GetFileNameForKeyBadCharacter);
    FRIEND_TEST(PrefsTest, GetFileNameForKeyEmpty);

    // Sets |filename| to the full path to the file containing the data
    // associated with |key|. Returns true on success, false otherwise.
    bool GetFileNameForKey(const std::string& key,
                           base::FilePath* filename) const;

    // Preference store directory.
    base::FilePath prefs_dir_;
  };

  // The concrete file storage implementation.
  FileStorage file_storage_;

  DISALLOW_COPY_AND_ASSIGN(Prefs);
};

// Implements a preference store in memory. The stored values are lost when the
// object is destroyed.

class MemoryPrefs : public PrefsBase {
 public:
  MemoryPrefs() : PrefsBase(&mem_storage_) {}

 private:
  class MemoryStorage : public PrefsBase::StorageInterface {
   public:
    MemoryStorage() = default;

    // PrefsBase::StorageInterface overrides.
    bool GetKey(const std::string& key, std::string* value) const override;
    bool GetSubKeys(const std::string& ns,
                    std::vector<std::string>* keys) const override;
    bool SetKey(const std::string& key, const std::string& value) override;
    bool KeyExists(const std::string& key) const override;
    bool DeleteKey(const std::string& key) override;

   private:
    // The std::map holding the values in memory.
    std::map<std::string, std::string> values_;
  };

  // The concrete memory storage implementation.
  MemoryStorage mem_storage_;

  DISALLOW_COPY_AND_ASSIGN(MemoryPrefs);
};
}  // namespace chromeos_update_engine

#endif  // UPDATE_ENGINE_COMMON_PREFS_H_
