// Copyright 2020 The Abseil Authors.
//
// 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
//
//      https://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 "absl/strings/internal/str_format/bind.h"

#include <cerrno>
#include <limits>
#include <sstream>
#include <string>

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {

namespace {

inline bool BindFromPosition(int position, int* value,
                             absl::Span<const FormatArgImpl> pack) {
  assert(position > 0);
  if (static_cast<size_t>(position) > pack.size()) {
    return false;
  }
  // -1 because positions are 1-based
  return FormatArgImplFriend::ToInt(pack[position - 1], value);
}

class ArgContext {
 public:
  explicit ArgContext(absl::Span<const FormatArgImpl> pack) : pack_(pack) {}

  // Fill 'bound' with the results of applying the context's argument pack
  // to the specified 'unbound'. We synthesize a BoundConversion by
  // lining up a UnboundConversion with a user argument. We also
  // resolve any '*' specifiers for width and precision, so after
  // this call, 'bound' has all the information it needs to be formatted.
  // Returns false on failure.
  bool Bind(const UnboundConversion* unbound, BoundConversion* bound);

 private:
  absl::Span<const FormatArgImpl> pack_;
};

inline bool ArgContext::Bind(const UnboundConversion* unbound,
                             BoundConversion* bound) {
  const FormatArgImpl* arg = nullptr;
  int arg_position = unbound->arg_position;
  if (static_cast<size_t>(arg_position - 1) >= pack_.size()) return false;
  arg = &pack_[arg_position - 1];  // 1-based

  if (unbound->flags != Flags::kBasic) {
    int width = unbound->width.value();
    bool force_left = false;
    if (unbound->width.is_from_arg()) {
      if (!BindFromPosition(unbound->width.get_from_arg(), &width, pack_))
        return false;
      if (width < 0) {
        // "A negative field width is taken as a '-' flag followed by a
        // positive field width."
        force_left = true;
        // Make sure we don't overflow the width when negating it.
        width = -std::max(width, -std::numeric_limits<int>::max());
      }
    }

    int precision = unbound->precision.value();
    if (unbound->precision.is_from_arg()) {
      if (!BindFromPosition(unbound->precision.get_from_arg(), &precision,
                            pack_))
        return false;
    }

    FormatConversionSpecImplFriend::SetWidth(width, bound);
    FormatConversionSpecImplFriend::SetPrecision(precision, bound);

    if (force_left) {
      FormatConversionSpecImplFriend::SetFlags(unbound->flags | Flags::kLeft,
                                               bound);
    } else {
      FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
    }
  } else {
    FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
    FormatConversionSpecImplFriend::SetWidth(-1, bound);
    FormatConversionSpecImplFriend::SetPrecision(-1, bound);
  }
  FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound);
  bound->set_arg(arg);
  return true;
}

template <typename Converter>
class ConverterConsumer {
 public:
  ConverterConsumer(Converter converter, absl::Span<const FormatArgImpl> pack)
      : converter_(converter), arg_context_(pack) {}

  bool Append(string_view s) {
    converter_.Append(s);
    return true;
  }
  bool ConvertOne(const UnboundConversion& conv, string_view conv_string) {
    BoundConversion bound;
    if (!arg_context_.Bind(&conv, &bound)) return false;
    return converter_.ConvertOne(bound, conv_string);
  }

 private:
  Converter converter_;
  ArgContext arg_context_;
};

template <typename Converter>
bool ConvertAll(const UntypedFormatSpecImpl format,
                absl::Span<const FormatArgImpl> args, Converter converter) {
  if (format.has_parsed_conversion()) {
    return format.parsed_conversion()->ProcessFormat(
        ConverterConsumer<Converter>(converter, args));
  } else {
    return ParseFormatString(format.str(),
                             ConverterConsumer<Converter>(converter, args));
  }
}

class DefaultConverter {
 public:
  explicit DefaultConverter(FormatSinkImpl* sink) : sink_(sink) {}

  void Append(string_view s) const { sink_->Append(s); }

  bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const {
    return FormatArgImplFriend::Convert(*bound.arg(), bound, sink_);
  }

 private:
  FormatSinkImpl* sink_;
};

class SummarizingConverter {
 public:
  explicit SummarizingConverter(FormatSinkImpl* sink) : sink_(sink) {}

  void Append(string_view s) const { sink_->Append(s); }

  bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const {
    UntypedFormatSpecImpl spec("%d");

    std::ostringstream ss;
    ss << "{" << Streamable(spec, {*bound.arg()}) << ":"
       << FormatConversionSpecImplFriend::FlagsToString(bound);
    if (bound.width() >= 0) ss << bound.width();
    if (bound.precision() >= 0) ss << "." << bound.precision();
    ss << bound.conversion_char() << "}";
    Append(ss.str());
    return true;
  }

 private:
  FormatSinkImpl* sink_;
};

}  // namespace

bool BindWithPack(const UnboundConversion* props,
                  absl::Span<const FormatArgImpl> pack,
                  BoundConversion* bound) {
  return ArgContext(pack).Bind(props, bound);
}

std::string Summarize(const UntypedFormatSpecImpl format,
                      absl::Span<const FormatArgImpl> args) {
  typedef SummarizingConverter Converter;
  std::string out;
  {
    // inner block to destroy sink before returning out. It ensures a last
    // flush.
    FormatSinkImpl sink(&out);
    if (!ConvertAll(format, args, Converter(&sink))) {
      return "";
    }
  }
  return out;
}

bool FormatUntyped(FormatRawSinkImpl raw_sink,
                   const UntypedFormatSpecImpl format,
                   absl::Span<const FormatArgImpl> args) {
  FormatSinkImpl sink(raw_sink);
  using Converter = DefaultConverter;
  return ConvertAll(format, args, Converter(&sink));
}

std::ostream& Streamable::Print(std::ostream& os) const {
  if (!FormatUntyped(&os, format_, args_)) os.setstate(std::ios::failbit);
  return os;
}

std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format,
                        absl::Span<const FormatArgImpl> args) {
  size_t orig = out->size();
  if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) {
    out->erase(orig);
  }
  return *out;
}

std::string FormatPack(const UntypedFormatSpecImpl format,
                       absl::Span<const FormatArgImpl> args) {
  std::string out;
  if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) {
    out.clear();
  }
  return out;
}

int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
            absl::Span<const FormatArgImpl> args) {
  FILERawSink sink(output);
  if (!FormatUntyped(&sink, format, args)) {
    errno = EINVAL;
    return -1;
  }
  if (sink.error()) {
    errno = sink.error();
    return -1;
  }
  if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
    errno = EFBIG;
    return -1;
  }
  return static_cast<int>(sink.count());
}

int SnprintF(char* output, size_t size, const UntypedFormatSpecImpl format,
             absl::Span<const FormatArgImpl> args) {
  BufferRawSink sink(output, size ? size - 1 : 0);
  if (!FormatUntyped(&sink, format, args)) {
    errno = EINVAL;
    return -1;
  }
  size_t total = sink.total_written();
  if (size) output[std::min(total, size - 1)] = 0;
  return static_cast<int>(total);
}

}  // namespace str_format_internal
ABSL_NAMESPACE_END
}  // namespace absl
