/*
 * Copyright 2016 Google Inc. All rights reserved.
 *
 * 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 "flatbuffers/code_generators.h"

#include <assert.h>

#include <cmath>

#include "flatbuffers/base.h"
#include "flatbuffers/util.h"

#if defined(_MSC_VER)
#  pragma warning(push)
#  pragma warning(disable : 4127)  // C4127: conditional expression is constant
#endif

namespace flatbuffers {

void CodeWriter::operator+=(std::string text) {
  if (!ignore_ident_ && !text.empty()) AppendIdent(stream_);

  while (true) {
    auto begin = text.find("{{");
    if (begin == std::string::npos) { break; }

    auto end = text.find("}}");
    if (end == std::string::npos || end < begin) { break; }

    // Write all the text before the first {{ into the stream.
    stream_.write(text.c_str(), begin);

    // The key is between the {{ and }}.
    const std::string key = text.substr(begin + 2, end - begin - 2);

    // Find the value associated with the key.  If it exists, write the
    // value into the stream, otherwise write the key itself into the stream.
    auto iter = value_map_.find(key);
    if (iter != value_map_.end()) {
      const std::string &value = iter->second;
      stream_ << value;
    } else {
      FLATBUFFERS_ASSERT(false && "could not find key");
      stream_ << key;
    }

    // Update the text to everything after the }}.
    text = text.substr(end + 2);
  }
  if (!text.empty() && string_back(text) == '\\') {
    text.pop_back();
    ignore_ident_ = true;
    stream_ << text;
  } else {
    ignore_ident_ = false;
    stream_ << text << std::endl;
  }
}

void CodeWriter::AppendIdent(std::stringstream &stream) {
  int lvl = cur_ident_lvl_;
  while (lvl--) {
    stream.write(pad_.c_str(), static_cast<std::streamsize>(pad_.size()));
  }
}

const char *BaseGenerator::FlatBuffersGeneratedWarning() {
  return "automatically generated by the FlatBuffers compiler,"
         " do not modify";
}

std::string BaseGenerator::NamespaceDir(const Parser &parser,
                                        const std::string &path,
                                        const Namespace &ns,
                                        const bool dasherize) {
  EnsureDirExists(path);
  if (parser.opts.one_file) return path;
  std::string namespace_dir = path;  // Either empty or ends in separator.
  auto &namespaces = ns.components;
  for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
    namespace_dir += !dasherize ? *it : ToDasherizedCase(*it);
    namespace_dir += kPathSeparator;
    EnsureDirExists(namespace_dir);
  }
  return namespace_dir;
}

std::string BaseGenerator::NamespaceDir(const Namespace &ns,
                                        const bool dasherize) const {
  return BaseGenerator::NamespaceDir(parser_, path_, ns, dasherize);
}

std::string BaseGenerator::ToDasherizedCase(const std::string pascal_case) {
  std::string dasherized_case;
  char p = 0;
  for (size_t i = 0; i < pascal_case.length(); i++) {
    char const &c = pascal_case[i];
    if (is_alpha_upper(c)) {
      if (i > 0 && p != kPathSeparator) dasherized_case += "-";
      dasherized_case += CharToLower(c);
    } else {
      dasherized_case += c;
    }
    p = c;
  }
  return dasherized_case;
}

std::string BaseGenerator::FullNamespace(const char *separator,
                                         const Namespace &ns) {
  std::string namespace_name;
  auto &namespaces = ns.components;
  for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
    if (namespace_name.length()) namespace_name += separator;
    namespace_name += *it;
  }
  return namespace_name;
}

std::string BaseGenerator::LastNamespacePart(const Namespace &ns) {
  if (!ns.components.empty())
    return ns.components.back();
  else
    return std::string("");
}

// Ensure that a type is prefixed with its namespace.
std::string BaseGenerator::WrapInNameSpace(const Namespace *ns,
                                           const std::string &name) const {
  std::string qualified_name = qualifying_start_;
  for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
    qualified_name += *it + qualifying_separator_;
  return qualified_name + name;
}

std::string BaseGenerator::WrapInNameSpace(const Definition &def) const {
  return WrapInNameSpace(def.defined_namespace, def.name);
}

std::string BaseGenerator::GetNameSpace(const Definition &def) const {
  const Namespace *ns = def.defined_namespace;
  if (CurrentNameSpace() == ns) return "";
  std::string qualified_name = qualifying_start_;
  for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
    qualified_name += *it;
    if ((it + 1) != ns->components.end()) {
      qualified_name += qualifying_separator_;
    }
  }

  return qualified_name;
}

std::string BaseGenerator::GeneratedFileName(const std::string &path,
                                             const std::string &file_name,
                                             const IDLOptions &options) const {
  return path + file_name + options.filename_suffix + "." +
         (options.filename_extension.empty() ? default_extension_
                                             : options.filename_extension);
}

// Generate a documentation comment, if available.
void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
                const CommentConfig *config, const char *prefix) {
  if (dc.begin() == dc.end()) {
    // Don't output empty comment blocks with 0 lines of comment content.
    return;
  }

  std::string &code = *code_ptr;
  if (config != nullptr && config->first_line != nullptr) {
    code += std::string(prefix) + std::string(config->first_line) + "\n";
  }
  std::string line_prefix =
      std::string(prefix) +
      ((config != nullptr && config->content_line_prefix != nullptr)
           ? config->content_line_prefix
           : "///");
  for (auto it = dc.begin(); it != dc.end(); ++it) {
    code += line_prefix + *it + "\n";
  }
  if (config != nullptr && config->last_line != nullptr) {
    code += std::string(prefix) + std::string(config->last_line) + "\n";
  }
}

template<typename T>
std::string FloatConstantGenerator::GenFloatConstantImpl(
    const FieldDef &field) const {
  const auto &constant = field.value.constant;
  T v;
  auto done = StringToNumber(constant.c_str(), &v);
  FLATBUFFERS_ASSERT(done);
  if (done) {
#if (!defined(_MSC_VER) || (_MSC_VER >= 1800))
    if (std::isnan(v)) return NaN(v);
    if (std::isinf(v)) return Inf(v);
#endif
    return Value(v, constant);
  }
  return "#";  // compile time error
}

std::string FloatConstantGenerator::GenFloatConstant(
    const FieldDef &field) const {
  switch (field.value.type.base_type) {
    case BASE_TYPE_FLOAT: return GenFloatConstantImpl<float>(field);
    case BASE_TYPE_DOUBLE: return GenFloatConstantImpl<double>(field);
    default: {
      FLATBUFFERS_ASSERT(false);
      return "INVALID_BASE_TYPE";
    }
  };
}

TypedFloatConstantGenerator::TypedFloatConstantGenerator(
    const char *double_prefix, const char *single_prefix,
    const char *nan_number, const char *pos_inf_number,
    const char *neg_inf_number)
    : double_prefix_(double_prefix),
      single_prefix_(single_prefix),
      nan_number_(nan_number),
      pos_inf_number_(pos_inf_number),
      neg_inf_number_(neg_inf_number) {}

std::string TypedFloatConstantGenerator::MakeNaN(
    const std::string &prefix) const {
  return prefix + nan_number_;
}
std::string TypedFloatConstantGenerator::MakeInf(
    bool neg, const std::string &prefix) const {
  if (neg)
    return !neg_inf_number_.empty() ? (prefix + neg_inf_number_)
                                    : ("-" + prefix + pos_inf_number_);
  else
    return prefix + pos_inf_number_;
}

std::string TypedFloatConstantGenerator::Value(double v,
                                               const std::string &src) const {
  (void)v;
  return src;
}

std::string TypedFloatConstantGenerator::Inf(double v) const {
  return MakeInf(v < 0, double_prefix_);
}

std::string TypedFloatConstantGenerator::NaN(double v) const {
  (void)v;
  return MakeNaN(double_prefix_);
}

std::string TypedFloatConstantGenerator::Value(float v,
                                               const std::string &src) const {
  (void)v;
  return src + "f";
}

std::string TypedFloatConstantGenerator::Inf(float v) const {
  return MakeInf(v < 0, single_prefix_);
}

std::string TypedFloatConstantGenerator::NaN(float v) const {
  (void)v;
  return MakeNaN(single_prefix_);
}

SimpleFloatConstantGenerator::SimpleFloatConstantGenerator(
    const char *nan_number, const char *pos_inf_number,
    const char *neg_inf_number)
    : nan_number_(nan_number),
      pos_inf_number_(pos_inf_number),
      neg_inf_number_(neg_inf_number) {}

std::string SimpleFloatConstantGenerator::Value(double v,
                                                const std::string &src) const {
  (void)v;
  return src;
}

std::string SimpleFloatConstantGenerator::Inf(double v) const {
  return (v < 0) ? neg_inf_number_ : pos_inf_number_;
}

std::string SimpleFloatConstantGenerator::NaN(double v) const {
  (void)v;
  return nan_number_;
}

std::string SimpleFloatConstantGenerator::Value(float v,
                                                const std::string &src) const {
  return this->Value(static_cast<double>(v), src);
}

std::string SimpleFloatConstantGenerator::Inf(float v) const {
  return this->Inf(static_cast<double>(v));
}

std::string SimpleFloatConstantGenerator::NaN(float v) const {
  return this->NaN(static_cast<double>(v));
}

std::string JavaCSharpMakeRule(const Parser &parser, const std::string &path,
                               const std::string &file_name) {
  FLATBUFFERS_ASSERT(parser.opts.lang == IDLOptions::kJava ||
                     parser.opts.lang == IDLOptions::kCSharp);

  std::string file_extension =
      (parser.opts.lang == IDLOptions::kJava) ? ".java" : ".cs";

  std::string make_rule;

  for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end();
       ++it) {
    auto &enum_def = **it;
    if (!make_rule.empty()) make_rule += " ";
    std::string directory =
        BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace);
    make_rule += directory + enum_def.name + file_extension;
  }

  for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
       ++it) {
    auto &struct_def = **it;
    if (!make_rule.empty()) make_rule += " ";
    std::string directory = BaseGenerator::NamespaceDir(
        parser, path, *struct_def.defined_namespace);
    make_rule += directory + struct_def.name + file_extension;
  }

  make_rule += ": ";
  auto included_files = parser.GetIncludedFilesRecursive(file_name);
  for (auto it = included_files.begin(); it != included_files.end(); ++it) {
    make_rule += " " + *it;
  }
  return make_rule;
}

std::string BinaryFileName(const Parser &parser, const std::string &path,
                           const std::string &file_name) {
  auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin";
  return path + file_name + "." + ext;
}

bool GenerateBinary(const Parser &parser, const std::string &path,
                    const std::string &file_name) {
  if (parser.opts.use_flexbuffers) {
    auto data_vec = parser.flex_builder_.GetBuffer();
    auto data_ptr = reinterpret_cast<char *>(data(data_vec));
    return !parser.flex_builder_.GetSize() ||
           flatbuffers::SaveFile(
               BinaryFileName(parser, path, file_name).c_str(), data_ptr,
               parser.flex_builder_.GetSize(), true);
  }
  return !parser.builder_.GetSize() ||
         flatbuffers::SaveFile(
             BinaryFileName(parser, path, file_name).c_str(),
             reinterpret_cast<char *>(parser.builder_.GetBufferPointer()),
             parser.builder_.GetSize(), true);
}

std::string BinaryMakeRule(const Parser &parser, const std::string &path,
                           const std::string &file_name) {
  if (!parser.builder_.GetSize()) return "";
  std::string filebase =
      flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
  std::string make_rule =
      BinaryFileName(parser, path, filebase) + ": " + file_name;
  auto included_files =
      parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
  for (auto it = included_files.begin(); it != included_files.end(); ++it) {
    make_rule += " " + *it;
  }
  return make_rule;
}

}  // namespace flatbuffers

#if defined(_MSC_VER)
#  pragma warning(pop)
#endif
