#include "image_io/base/data_context.h"

#include <cctype>
#include <iomanip>
#include <sstream>

#include "image_io/base/byte_data.h"

namespace photos_editing_formats {
namespace image_io {

namespace {

void AddNames(const std::list<std::string>& name_list, std::stringstream* ss) {
  for (const auto& name : name_list) {
    *ss << name << ":";
  }
}

}  // namespace

std::string DataContext::GetInvalidLocationAndRangeErrorText() const {
  std::stringstream ss;
  ss << "Invalid location:" << location_ << " range:[" << range_.GetBegin()
     << "," << range_.GetEnd() << ") segment_range:["
     << segment_.GetDataRange().GetBegin() << ","
     << segment_.GetDataRange().GetEnd() << ")";
  return GetErrorText(ss.str(), "");
}

std::string DataContext::GetErrorText(
    const std::string& error_description,
    const std::string& expectation_description) const {
  std::list<std::string> none;
  return GetErrorText(none, none, error_description, expectation_description);
}

std::string DataContext::GetErrorText(
    const std::list<std::string>& prefix_name_list,
    const std::list<std::string>& postfix_name_list,
    const std::string& error_description,
    const std::string& expectation_description) const {
  const std::string kContinue("- ");
  std::stringstream ss;

  // Write error description if present.
  if (!error_description.empty()) {
    ss << error_description << std::endl;
  }

  // Write name:name:... if present.
  std::string names_string =
      GetNamesString(prefix_name_list, postfix_name_list);
  if (!names_string.empty()) {
    ss << kContinue << names_string << std::endl;
  }

  // Get the line:XX part of the line string.
  DataLine data_line;
  std::string line_number_string;
  if (IsValidLocationAndRange()) {
    data_line = line_info_map_.GetDataLine(location_);
    line_number_string = GetLineNumberString(data_line);
  }

  // Get the line_string related ranges and the line string.
  DataRange clipped_range, line_range;
  size_t spaces_before_caret = line_number_string.length();
  GetClippedAndLineRange(data_line, &clipped_range, &line_range);
  std::string line_string =
      GetLineString(clipped_range, line_range, &spaces_before_caret);

  // Write the line string
  ss << kContinue << line_number_string << line_string << std::endl;

  // Write the caret and expectation description
  size_t spaces_count = location_ + spaces_before_caret - line_range.GetBegin();
  std::string spaces(spaces_count, ' ');
  ss << kContinue << spaces << '^';
  if (!expectation_description.empty()) {
    ss << "expected:" << expectation_description;
  }
  return ss.str();
}

std::string DataContext::GetNamesString(
    const std::list<std::string>& prefix_name_list,
    const std::list<std::string>& postfix_name_list) const {
  std::stringstream ss;
  if (!prefix_name_list.empty() || !name_list_.empty() ||
      !postfix_name_list.empty()) {
    AddNames(prefix_name_list, &ss);
    AddNames(name_list_, &ss);
    AddNames(postfix_name_list, &ss);
  }
  return ss.str();
}

std::string DataContext::GetLineNumberString(const DataLine& data_line) const {
  std::stringstream liness;
  liness << "line:";
  if (data_line.number == 0) {
    liness << "?:";
  } else {
    liness << data_line.number << ":";
  }
  return liness.str();
}

void DataContext::GetClippedAndLineRange(const DataLine& data_line,
                                         DataRange* clipped_range,
                                         DataRange* line_range) const {
  // Lines could be really long, so provide some sane limits: some kLimit chars
  // on either side of the current location.
  const size_t kLimit = 25;
  size_t line_begin, line_end;
  *clipped_range = data_line.range.IsValid()
                       ? range_.GetIntersection(data_line.range)
                       : range_;
  if (clipped_range->IsValid() && clipped_range->Contains(location_)) {
    line_begin = (clipped_range->GetBegin() + kLimit < location_)
                     ? location_ - kLimit
                     : clipped_range->GetBegin();
    line_end = std::min(line_begin + 2 * kLimit, clipped_range->GetEnd());
  } else {
    line_begin = location_;
    line_end = std::min(location_ + 2 * kLimit, range_.GetEnd());
    *clipped_range = DataRange(line_begin, line_end);
  }
  *line_range = DataRange(line_begin, line_end);
}

std::string DataContext::GetLineString(const DataRange& clipped_range,
                                       const DataRange& line_range,
                                       size_t* spaces_before_caret) const {
  std::stringstream ss;
  if (!IsValidLocationAndRange()) {
    ss << "Invalid location or range";
    return ss.str();
  }

  const char* cbytes =
      reinterpret_cast<const char*>(segment_.GetBuffer(line_range.GetBegin()));
  if (cbytes != nullptr) {
    if (line_range.GetBegin() != clipped_range.GetBegin()) {
      ss << "...";
      *spaces_before_caret += 3;
    }
    for (size_t index = 0; index < line_range.GetLength(); ++index) {
      char cbyte = cbytes[index];
      if (isprint(cbyte)) {
        ss << cbyte;
      } else {
        ss << "\\x" << ByteData::Byte2Hex(cbyte);
        if (index + line_range.GetBegin() < location_) {
          *spaces_before_caret += 4;
        }
      }
    }
    if (line_range.GetEnd() != clipped_range.GetEnd()) {
      ss << "...";
    }
  }
  return ss.str();
}

}  // namespace image_io
}  // namespace photos_editing_formats
