// Copyright 2019 The Chromium OS Authors. All rights reserved.
// 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
