// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shill/pending_activation_store.h"

#include "shill/key_file_store.h"
#include "shill/logging.h"

using base::FilePath;
using std::string;

namespace shill {

const char PendingActivationStore::kIccidGroupId[] = "iccid_list";
const char PendingActivationStore::kMeidGroupId[] = "meid_list";
// We're keeping the old file name here for backwards compatibility.
const char PendingActivationStore::kStorageFileName[] =
    "activating_iccid_store.profile";

PendingActivationStore::PendingActivationStore() {}

PendingActivationStore::~PendingActivationStore() {
  if (storage_.get())
    storage_->Flush();  // Make certain that everything is persisted.
}

namespace {

string StateToString(PendingActivationStore::State state) {
  switch (state) {
    case PendingActivationStore::kStateUnknown:
      return "Unknown";
    case PendingActivationStore::kStatePending:
      return "Pending";
    case PendingActivationStore::kStateActivated:
      return "Activated";
    case PendingActivationStore::kStatePendingTimeout:
      return "PendingTimeout";
    default:
      return "Invalid";
  }
}

string FormattedIdentifier(PendingActivationStore::IdentifierType type,
                           const string &identifier) {
  string label;
  switch (type) {
    case PendingActivationStore::kIdentifierICCID:
      label = "ICCID";
      break;
    case PendingActivationStore::kIdentifierMEID:
      label = "MEID";
      break;
    default:
      NOTREACHED();
  }
  return "[" + label + "=" + identifier + "]";
}

}  // namespace

// static
string PendingActivationStore::IdentifierTypeToGroupId(IdentifierType type) {
  switch(type) {
    case kIdentifierICCID:
      return kIccidGroupId;
    case kIdentifierMEID:
      return kMeidGroupId;
    default:
      SLOG(Cellular, 2) << "Incorrect identifier type: " << type;
      return "";
  }
}

bool PendingActivationStore::InitStorage(
    GLib *glib,
    const FilePath &storage_path) {
  // Close the current file.
  if (storage_.get()) {
    storage_->Flush();
    storage_.reset();  // KeyFileStore closes the file in its destructor.
  }
  if (!glib) {
    LOG(ERROR) << "Null pointer passed for |glib|.";
    return false;
  }
  if (storage_path.empty()) {
    LOG(ERROR) << "Empty storage directory path provided.";
    return false;
  }
  FilePath path = storage_path.Append(kStorageFileName);
  scoped_ptr<KeyFileStore> storage(new KeyFileStore(glib));
  storage->set_path(path);
  bool already_exists = storage->IsNonEmpty();
  if (!storage->Open()) {
    LOG(ERROR) << "Failed to open file at '" << path.AsUTF8Unsafe()  << "'";
    if (already_exists)
      storage->MarkAsCorrupted();
    return false;
  }
  if (!already_exists)
    storage->SetHeader("Identifiers pending cellular activation.");
  storage_.reset(storage.release());
  return true;
}

PendingActivationStore::State PendingActivationStore::GetActivationState(
    IdentifierType type,
    const string &identifier) const {
  string formatted_identifier = FormattedIdentifier(type, identifier);
  SLOG(Cellular, 2) << __func__ << ": " << formatted_identifier;
  if (!storage_.get()) {
    LOG(ERROR) << "Underlying storage not initialized.";
    return kStateUnknown;
  }
  int state = 0;
  if (!storage_->GetInt(IdentifierTypeToGroupId(type), identifier, &state)) {
    SLOG(Cellular, 2) << "No entry exists for " << formatted_identifier;
    return kStateUnknown;
  }
  if (state <= 0 || state >= kStateMax) {
    SLOG(Cellular, 2) << "State value read for " << formatted_identifier
                      << " is invalid.";
    return kStateUnknown;
  }
  return static_cast<State>(state);
}

bool PendingActivationStore::SetActivationState(
    IdentifierType type,
    const string &identifier,
    State state) {
  SLOG(Cellular, 2) << __func__ << ": State=" << StateToString(state) << ", "
                    << FormattedIdentifier(type, identifier);
  if (!storage_.get()) {
    LOG(ERROR) << "Underlying storage not initialized.";
    return false;
  }
  if (state == kStateUnknown) {
    SLOG(Cellular, 2) << "kStateUnknown cannot be used as a value.";
    return false;
  }
  if (state < 0 || state >= kStateMax) {
    SLOG(Cellular, 2) << "Cannot set state to \"" << StateToString(state)
                      << "\"";
    return false;
  }
  if (!storage_->SetInt(
      IdentifierTypeToGroupId(type), identifier, static_cast<int>(state))) {
    SLOG(Cellular, 2) << "Failed to store the given identifier and state "
                      << "values.";
    return false;
  }
  return storage_->Flush();
}

bool PendingActivationStore::RemoveEntry(IdentifierType type,
                                         const std::string &identifier) {
  SLOG(Cellular, 2) << __func__ << ": "
                    << FormattedIdentifier(type, identifier);
  if (!storage_.get()) {
    LOG(ERROR) << "Underlying storage not initialized.";
    return false;
  }
  if (!storage_->DeleteKey(IdentifierTypeToGroupId(type), identifier)) {
    SLOG(Cellular, 2) << "Failed to remove the given identifier.";
    return false;
  }
  return storage_->Flush();
}

}  // namespace shill
