// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "libipp/ipp_frame_builder.h"

#include <algorithm>

#include "libipp/ipp_attribute.h"
#include "libipp/ipp_encoding.h"

namespace ipp {

namespace {

// Saves 1-,2- or 4-bytes integer to buf using two's-complement binary encoding.
// The "buf" parameter is always resized to BytesCount. Returns false when
// given integer is out of range. In this case 0 is saved to buf.
template <size_t BytesCount>
bool SaveInteger(int v, std::vector<uint8_t>* buf) {
  buf->resize(BytesCount);
  uint8_t* ptr = buf->data();
  if (!WriteInteger<BytesCount>(&ptr, v)) {
    buf->clear();
    buf->resize(BytesCount, 0);
    return false;
  }
  return true;
}

// Saves simple string to buf, buf is resized accordingly.
void SaveOctetString(const std::string& s, std::vector<uint8_t>* buf) {
  buf->assign(s.begin(), s.end());
}

// Writes textWithLanguage/nameWithLanguage (see [rfc8010]) to buf, which is
// resized accordingly. Returns false if given string(s) is too long. In this
// case an empty string is saved to the buffer.
bool SaveStringWithLanguage(const ipp::StringWithLanguage& s,
                            std::vector<uint8_t>* buf) {
  buf->clear();
  buf->resize(4 + s.value.size() + s.language.size());
  uint8_t* ptr = buf->data();
  if (!WriteInteger<2>(&ptr, s.language.size())) {
    std::vector<uint8_t> empty_buffer(4, 0);
    buf->swap(empty_buffer);
    return false;
  }
  ptr = std::copy(s.language.begin(), s.language.end(), ptr);
  if (!WriteInteger<2>(&ptr, s.value.size())) {
    std::vector<uint8_t> empty_buffer(4, 0);
    buf->swap(empty_buffer);
    return false;
  }
  std::copy(s.value.begin(), s.value.end(), ptr);
  return true;
}

// Saves dateTime (see [rfc8010]) to buf, which is resized accordingly. Returns
// false when the given dateTime is incorrect; in this case |buf| is set to
// 2000/1/1 00:00:00 +00:00.
bool SaveDateTime(const ipp::DateTime& v, std::vector<uint8_t>* buf) {
  buf->resize(11);
  uint8_t* ptr = buf->data();
  if (WriteInteger<2>(&ptr, v.year) && WriteInteger<1>(&ptr, v.month) &&
      WriteInteger<1>(&ptr, v.day) && WriteInteger<1>(&ptr, v.hour) &&
      WriteInteger<1>(&ptr, v.minutes) && WriteInteger<1>(&ptr, v.seconds) &&
      WriteInteger<1>(&ptr, v.deci_seconds) &&
      WriteInteger<1>(&ptr, v.UTC_direction) &&
      WriteInteger<1>(&ptr, v.UTC_hours) &&
      WriteInteger<1>(&ptr, v.UTC_minutes))
    return true;
  buf->clear();
  buf->resize(11, 0);
  ptr = buf->data();
  WriteInteger<int16_t>(&ptr, 2000);
  (*buf)[8] = '+';
  return false;
}

// Writes resolution (see [rfc8010]) to buf, which is resized accordingly.
// Returns false when given value is incorrect; in this case |buf| is set to
// 256x256dpi.
bool SaveResolution(const ipp::Resolution& v, std::vector<uint8_t>* buf) {
  buf->resize(9);
  uint8_t* ptr = buf->data();
  if (WriteInteger<4>(&ptr, v.xres) && WriteInteger<4>(&ptr, v.yres) &&
      (v.units == ipp::Resolution::kDotsPerCentimeter ||
       v.units == ipp::Resolution::kDotsPerInch)) {
    WriteInteger<int8_t>(&ptr, v.units);
    return true;
  }
  buf->clear();
  // set to 256x256 dpi
  buf->resize(9, 0);
  (*buf)[2] = (*buf)[6] = 1;
  (*buf)[8] = ipp::Resolution::kDotsPerInch;
  return false;
}

// Writes rangeOfInteger (see [rfc8010]) to buf, which is resized accordingly.
// Returns false when given value is incorrect; in this case |buf| is set to 0.
bool SaveRangeOfInteger(const ipp::RangeOfInteger& v,
                        std::vector<uint8_t>* buf) {
  buf->resize(8);
  uint8_t* ptr = buf->data();
  if (WriteInteger<4>(&ptr, v.min_value) && WriteInteger<4>(&ptr, v.max_value))
    return true;
  buf->clear();
  buf->resize(8, 0);
  return false;
}

}  //  namespace

void FrameBuilder::LogFrameBuilderError(const std::string& message) {
  Log l;
  l.message = "Error when building frame: " + message + ".";
  errors_->push_back(l);
}

void FrameBuilder::SaveAttrValue(const Attribute* attr,
                                 size_t index,
                                 uint8_t* tag,
                                 std::vector<uint8_t>* buf) {
  *tag = static_cast<uint8_t>(attr->GetType());
  bool result = true;
  switch (attr->GetType()) {
    case AttrType::boolean: {
      int v = 0;
      attr->GetValue(&v, index);
      if (v != 0)
        v = 1;
      result = SaveInteger<1>(v, buf);
      break;
    }
    case AttrType::integer:
    case AttrType::enum_: {
      int v = 0;
      attr->GetValue(&v, index);
      result = SaveInteger<4>(v, buf);
      break;
    }
    case AttrType::dateTime: {
      DateTime v;
      attr->GetValue(&v, index);
      result = SaveDateTime(v, buf);
      break;
    }
    case AttrType::resolution: {
      Resolution v;
      attr->GetValue(&v, index);
      result = SaveResolution(v, buf);
      break;
    }
    case AttrType::rangeOfInteger: {
      RangeOfInteger v;
      attr->GetValue(&v, index);
      result = SaveRangeOfInteger(v, buf);
      break;
    }
    case AttrType::text: {
      StringWithLanguage s;
      attr->GetValue(&s, index);
      if (s.language.empty()) {
        *tag = textWithoutLanguage_value_tag;
        SaveOctetString(s, buf);
      } else {
        result = SaveStringWithLanguage(s, buf);
      }
    } break;
    case AttrType::name: {
      StringWithLanguage s;
      attr->GetValue(&s, index);
      if (s.language.empty()) {
        *tag = nameWithoutLanguage_value_tag;
        SaveOctetString(s, buf);
      } else {
        result = SaveStringWithLanguage(s, buf);
      }
    } break;
    case AttrType::octetString:
    case AttrType::keyword:
    case AttrType::uri:
    case AttrType::uriScheme:
    case AttrType::charset:
    case AttrType::naturalLanguage:
    case AttrType::mimeMediaType: {
      std::string s = "";
      attr->GetValue(&s, index);
      SaveOctetString(s, buf);
      break;
    }
    default:
      LogFrameBuilderError(
          "Internal error: cannot recognize value type of the attribute " +
          attr->GetName());
      buf->clear();
      break;
  }
  if (!result)
    LogFrameBuilderError("Incorrect value of the attribute " + attr->GetName() +
                         ". Default value was written instead");
}

void FrameBuilder::SaveCollection(const Collection* coll,
                                  std::list<TagNameValue>* data_chunks) {
  // get list of all attributes
  std::vector<const Attribute*> attrs = coll->GetAllAttributes();
  // save the attributes
  for (const Attribute* attr : attrs) {
    if (attr->GetState() == AttrState::unset)
      continue;
    TagNameValue tnv;
    tnv.tag = memberAttrName_value_tag;
    tnv.name.clear();
    SaveOctetString(attr->GetName(), &tnv.value);
    data_chunks->push_back(tnv);
    if (attr->GetState() != AttrState::set) {
      // out-of-band value (tag)
      tnv.tag = static_cast<uint8_t>(attr->GetState());
      tnv.value.clear();
      data_chunks->push_back(tnv);
    } else {
      // standard values (one or more)
      for (size_t val_index = 0; val_index < attr->GetSize(); ++val_index) {
        if (attr->GetType() == AttrType::collection) {
          tnv.tag = begCollection_value_tag;
          tnv.value.clear();
          data_chunks->push_back(tnv);
          SaveCollection(attr->GetCollection(val_index), data_chunks);
          tnv.tag = endCollection_value_tag;
          tnv.value.clear();
        } else {
          SaveAttrValue(attr, val_index, &tnv.tag, &tnv.value);
        }
        data_chunks->push_back(tnv);
      }
    }
  }
}

void FrameBuilder::SaveGroup(const Collection* coll,
                             std::list<TagNameValue>* data_chunks) {
  // get list of all attributes
  std::vector<const Attribute*> attrs = coll->GetAllAttributes();
  // save the attributes
  for (const Attribute* attr : attrs) {
    if (attr->GetState() == AttrState::unset)
      continue;
    TagNameValue tnv;
    SaveOctetString(attr->GetName(), &tnv.name);
    if (attr->GetState() != AttrState::set) {
      tnv.tag = static_cast<uint8_t>(attr->GetState());
      tnv.value.clear();
      data_chunks->push_back(tnv);
      continue;
    }
    for (size_t val_index = 0; val_index < attr->GetSize(); ++val_index) {
      if (attr->GetType() == AttrType::collection) {
        tnv.tag = begCollection_value_tag;
        tnv.value.clear();
        data_chunks->push_back(tnv);
        SaveCollection(attr->GetCollection(val_index), data_chunks);
        tnv.tag = endCollection_value_tag;
        tnv.name.clear();
        tnv.value.clear();
      } else {
        SaveAttrValue(attr, val_index, &tnv.tag, &tnv.value);
      }
      data_chunks->push_back(tnv);
      tnv.name.clear();
    }
  }
}

void FrameBuilder::BuildFrameFromPackage(const Package* package) {
  frame_->groups_tags_.clear();
  frame_->groups_content_.clear();
  // save frame data
  std::vector<const Group*> groups = package->GetAllGroups();
  for (const Group* grp : groups) {
    for (size_t i = 0; true; ++i) {
      const Collection* coll = grp->GetCollection(i);
      if (coll == nullptr)
        break;
      frame_->groups_tags_.push_back(static_cast<uint8_t>(grp->GetName()));
      frame_->groups_content_.resize(frame_->groups_tags_.size());
      SaveGroup(coll, &(frame_->groups_content_.back()));
      // skip if it this is a single empty group
      if (frame_->groups_content_.back().empty() && !grp->IsASet()) {
        frame_->groups_tags_.pop_back();
        frame_->groups_content_.pop_back();
      }
    }
  }
  frame_->data_ = package->Data();
}

bool FrameBuilder::WriteFrameToBuffer(uint8_t* ptr) {
  bool error_in_header = true;
  if (!WriteInteger<1>(&ptr, frame_->major_version_number_)) {
    LogFrameBuilderError("major-version-number is out of range");
  } else if (!WriteInteger<1>(&ptr, frame_->minor_version_number_)) {
    LogFrameBuilderError("minor-version-number is out of range");
  } else if (!WriteInteger<2>(&ptr, frame_->operation_id_or_status_code_)) {
    LogFrameBuilderError("operation-id or status-code is out of range");
  } else if (!WriteInteger<4>(&ptr, frame_->request_id_)) {
    LogFrameBuilderError("request-id is out of range");
  } else {
    error_in_header = false;
  }
  if (error_in_header)
    return false;
  for (size_t i = 0; i < frame_->groups_tags_.size(); ++i) {
    if (frame_->groups_tags_[i] > max_begin_attribute_group_tag) {
      LogFrameBuilderError("begin-attribute-group-tag is out of range");
      return false;
    }
    // write a group to the buffer
    if (!WriteInteger<1>(&ptr, frame_->groups_tags_[i]) ||
        !WriteTNVsToBuffer(frame_->groups_content_[i], &ptr))
      return false;
  }
  WriteInteger<int8_t>(&ptr, end_of_attributes_tag);
  std::copy(frame_->data_.begin(), frame_->data_.end(), ptr);
  return true;
}

bool FrameBuilder::WriteTNVsToBuffer(const std::list<TagNameValue>& tnvs,
                                     uint8_t** ptr) {
  for (auto& tnv : tnvs) {
    if (!WriteInteger<1>(ptr, tnv.tag)) {
      LogFrameBuilderError("value-tag is out of range");
      return false;
    }
    if (!WriteInteger<2>(ptr, tnv.name.size())) {
      LogFrameBuilderError("name-length is out of range");
      return false;
    }
    *ptr = std::copy(tnv.name.begin(), tnv.name.end(), *ptr);
    if (!WriteInteger<2>(ptr, tnv.value.size())) {
      LogFrameBuilderError("value-length is out of range");
      return false;
    }
    *ptr = std::copy(tnv.value.begin(), tnv.value.end(), *ptr);
  }
  return true;
}

std::size_t FrameBuilder::GetFrameLength() const {
  // Header has always 8 bytes (ipp_version + operation_id/status + request_id).
  size_t length = 8;
  // The header is followed by a list of groups.
  for (const auto& tnvs : frame_->groups_content_) {
    // Each group starts with 1-byte group-tag ...
    length += 1;
    // ... and consists of list of tag-name-value.
    for (const auto& tnv : tnvs)
      // Tag + name_size + name + value_size + value.
      length += (1 + 2 + tnv.name.size() + 2 + tnv.value.size());
  }
  // end-of-attributes-tag + blob_with_data.
  length += 1 + frame_->data_.size();
  return length;
}

}  // namespace ipp
