//
// 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 Delete(const std::string& pref_key,
              const std::vector<std::string>& nss) 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_
