/*
 * Copyright 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.
 */

#include <memory>

#include "dumpsys/filter.h"
#include "dumpsys/internal/filter_internal.h"
#include "os/log.h"

using namespace bluetooth;
using namespace dumpsys;

class Filter {
 public:
  Filter(const dumpsys::ReflectionSchema& reflection_schema) : reflection_schema_(reflection_schema) {}

  virtual ~Filter() = default;

  virtual void FilterInPlace(char* dumpsys_data) = 0;

  static std::unique_ptr<Filter> Factory(
      dumpsys::FilterType filter_type, const dumpsys::ReflectionSchema& reflection_schema);

 protected:
  /**
   * Given both reflection field data and the populated flatbuffer table data, if any,
   * filter the contents of the field based upon the filtering privacy level.
   *
   * Primitives and composite strings may be successfully processed at this point.
   * Other composite types (e.g. structs or tables) must be expanded into the
   * respective grouping of subfields.
   *
   * @param field The reflection field information from the bundled schema
   * @param table The populated field data, if any
   *
   * @return true if field was filtered successfully, false otherwise.
   */
  virtual bool FilterField(const reflection::Field* field, flatbuffers::Table* table) {
    return false;
  }

  /**
   * Given both reflection object data and the populated flatbuffer table data, if any,
   * filter the object fields based upon the filtering privacy level.
   *
   * @param object The reflection object information from the bundled schema
   * @param table The populated field data, if any
   *
   */
  virtual void FilterObject(const reflection::Object* object, flatbuffers::Table* table){};

  /**
   * Given both reflection field data and the populated table data, if any,
   * filter the contents of the table based upon the filtering privacy level.
   *
   * @param schema The reflection schema information from the bundled schema
   * @param table The populated field data, if any
   *
   */
  virtual void FilterTable(const reflection::Schema* schema, flatbuffers::Table* table){};

  const dumpsys::ReflectionSchema& reflection_schema_;
};

class DeveloperPrivacyFilter : public Filter {
 public:
  DeveloperPrivacyFilter(const dumpsys::ReflectionSchema& reflection_schema) : Filter(reflection_schema) {}
  void FilterInPlace(char* dumpsys_data) override {}
};

class UserPrivacyFilter : public Filter {
 public:
  UserPrivacyFilter(const dumpsys::ReflectionSchema& reflection_schema) : Filter(reflection_schema) {}
  void FilterInPlace(char* dumpsys_data) override;

 protected:
  bool FilterField(const reflection::Field* field, flatbuffers::Table* table) override;
  void FilterObject(const reflection::Object* object, flatbuffers::Table* table) override;
  void FilterTable(const reflection::Schema* schema, flatbuffers::Table* table) override;
};

bool UserPrivacyFilter::FilterField(const reflection::Field* field, flatbuffers::Table* table) {
  ASSERT(field != nullptr);
  ASSERT(table != nullptr);
  internal::PrivacyLevel privacy_level = internal::FindFieldPrivacyLevel(*field);

  switch (static_cast<flatbuffers::BaseType>(field->type()->base_type())) {
    case flatbuffers::BASE_TYPE_INT:
      return internal::FilterTypeInteger(*field, table, privacy_level);
      break;
    case flatbuffers::BASE_TYPE_FLOAT:
      return internal::FilterTypeFloat(*field, table, privacy_level);
      break;
    case flatbuffers::BASE_TYPE_STRING:
      return internal::FilterTypeString(*field, table, privacy_level);
      break;
    case flatbuffers::BASE_TYPE_STRUCT:
      return internal::FilterTypeStruct(*field, table, privacy_level);
      break;
    case flatbuffers::BASE_TYPE_BOOL:
      return internal::FilterTypeBool(*field, table, privacy_level);
      break;
    default:
      LOG_WARN("%s WARN Unsupported base type\n", __func__);
      break;
  }
  return false;
}

void UserPrivacyFilter::FilterObject(const reflection::Object* object, flatbuffers::Table* table) {
  ASSERT(object != nullptr);
  if (table == nullptr) {
    return;  // table data is not populated
  }
  for (auto it = object->fields()->cbegin(); it != object->fields()->cend(); ++it) {
    if (!FilterField(*it, table)) {
      LOG_ERROR("%s Unable to filter field from an object when it's expected it will work", __func__);
    };
  }
}

void UserPrivacyFilter::FilterTable(const reflection::Schema* schema, flatbuffers::Table* table) {
  if (schema == nullptr) {
    LOG_WARN("%s schema is nullptr...probably ok", __func__);
    return;
  }

  const reflection::Object* object = schema->root_table();
  if (object == nullptr) {
    LOG_WARN("%s reflection object is nullptr...is ok ?", __func__);
    return;
  }

  if (table == nullptr) {
    return;  // table not populated
  }

  for (auto it = object->fields()->cbegin(); it != object->fields()->cend(); ++it) {
    if (FilterField(*it, table)) {
      continue;  // Field successfully filtered
    }
    // Get the index of this complex non-string object from the schema which is
    // also the same index into the data table.
    int32_t index = it->type()->index();
    ASSERT(index != -1);

    flatbuffers::Table* sub_table = table->GetPointer<flatbuffers::Table*>(it->offset());
    const reflection::Schema* sub_schema =
        reflection_schema_.FindInReflectionSchema(schema->objects()->Get(index)->name()->str());

    if (sub_schema != nullptr) {
      FilterTable(sub_schema, sub_table);  // Top level schema
    } else {
      // Leaf node schema
      const flatbuffers::String* name = schema->objects()->Get(index)->name();
      const reflection::Object* sub_object = internal::FindReflectionObject(schema->objects(), name);
      if (sub_object != nullptr) {
        FilterObject(sub_object, sub_table);
      } else {
        LOG_ERROR("Unable to find reflection sub object:%s\n", name->c_str());
      }
    }
  }
}

void UserPrivacyFilter::FilterInPlace(char* dumpsys_data) {
  ASSERT(dumpsys_data != nullptr);
  const reflection::Schema* root_schema = reflection_schema_.FindInReflectionSchema(reflection_schema_.GetRootName());
  flatbuffers::Table* table = const_cast<flatbuffers::Table*>(flatbuffers::GetRoot<flatbuffers::Table>(dumpsys_data));
  FilterTable(root_schema, table);
}

std::unique_ptr<Filter> Filter::Factory(
    dumpsys::FilterType filter_type, const dumpsys::ReflectionSchema& reflection_schema) {
  switch (filter_type) {
    case dumpsys::FilterType::AS_DEVELOPER:
      return std::make_unique<DeveloperPrivacyFilter>(reflection_schema);
    default:
      return std::make_unique<UserPrivacyFilter>(reflection_schema);
  }
}

void bluetooth::dumpsys::FilterInPlace(
    FilterType filter_type, const ReflectionSchema& reflection_schema, std::string* dumpsys_data) {
  auto filter = Filter::Factory(filter_type, reflection_schema);
  filter->FilterInPlace(dumpsys_data->data());
}
