/*
 * Copyright (C) 2016 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 "java/ClassDefinition.h"

#include "androidfw/StringPiece.h"

using ::aapt::text::Printer;
using ::android::StringPiece;

namespace aapt {

void ClassMember::Print(bool /*final*/, Printer* printer, bool strip_api_annotations) const {
  processor_.Print(printer, strip_api_annotations);
}

void MethodDefinition::AppendStatement(StringPiece statement) {
  statements_.emplace_back(statement);
}

void MethodDefinition::Print(bool final, Printer* printer, bool) const {
  printer->Print(signature_).Println(" {");
  printer->Indent();
  for (const auto& statement : statements_) {
    printer->Println(statement);
  }
  printer->Undent();
  printer->Print("}");
}

ClassDefinition::Result ClassDefinition::AddMember(std::unique_ptr<ClassMember> member) {
  Result result = Result::kAdded;
  auto iter = indexed_members_.find(member->GetName());
  if (iter != indexed_members_.end()) {
    // Overwrite the entry. Be careful, as the key in indexed_members_ is actually memory owned
    // by the value at ordered_members_[index]. Since overwriting a value for a key doesn't replace
    // the key (the initial key inserted into the unordered_map is kept), we must erase and then
    // insert a new key, whose memory is being kept around. We do all this to avoid using more
    // memory for each key.
    size_t index = iter->second;

    // Erase the key + value from the map.
    indexed_members_.erase(iter);

    // Now clear the memory that was backing the key (now erased).
    ordered_members_[index].reset();
    result = Result::kOverridden;
  }

  indexed_members_[member->GetName()] = ordered_members_.size();
  ordered_members_.push_back(std::move(member));
  return result;
}

bool ClassDefinition::empty() const {
  for (const std::unique_ptr<ClassMember>& member : ordered_members_) {
    if (member != nullptr && !member->empty()) {
      return false;
    }
  }
  return true;
}

void ClassDefinition::Print(bool final, Printer* printer, bool strip_api_annotations) const {
  if (empty() && !create_if_empty_) {
    return;
  }

  ClassMember::Print(final,  printer, strip_api_annotations);

  printer->Print("public ");
  if (qualifier_ == ClassQualifier::kStatic) {
    printer->Print("static ");
  }
  printer->Print("final class ").Print(name_).Println(" {");
  printer->Indent();

  for (const std::unique_ptr<ClassMember>& member : ordered_members_) {
    // There can be nullptr members when a member is added to the ClassDefinition
    // and takes precedence over a previous member with the same name. The overridden member is
    // set to nullptr.
    if (member != nullptr) {
      member->Print(final, printer, strip_api_annotations);
      printer->Println();
    }
  }

  printer->Undent();
  printer->Print("}");
}

constexpr static const char* sWarningHeader =
    "/* AUTO-GENERATED FILE. DO NOT MODIFY.\n"
    " *\n"
    " * This class was automatically generated by the\n"
    " * aapt tool from the resource data it found. It\n"
    " * should not be modified by hand.\n"
    " */\n\n";

void ClassDefinition::WriteJavaFile(const ClassDefinition* def, StringPiece package, bool final,
                                    bool strip_api_annotations, android::OutputStream* out) {
  Printer printer(out);
  printer.Print(sWarningHeader).Print("package ").Print(package).Println(";");
  printer.Println();
  def->Print(final, &printer, strip_api_annotations);
}

}  // namespace aapt
