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

#include "frame.h"

#include <cstdint>
#include <memory>
#include <utility>
#include <vector>

#include "ipp_base.h"
#include "ipp_frame.h"
#include "ipp_frame_builder.h"
#include "ipp_parser.h"

namespace ipp {

// Min and max valid value of GroupTag. Keep in mind that in this range includes
// also invalid value 0x03.
constexpr GroupTag kMinGroupTag = static_cast<GroupTag>(0x01);
constexpr GroupTag kMaxGroupTag = static_cast<GroupTag>(0x0f);

constexpr size_t kMaxPayloadSize = 256 * 1024 * 1024;

namespace {

void SetCharsetAndLanguageAttributes(Frame* frame) {
  Collection* grp;
  frame->AddGroup(ipp::GroupTag::operation_attributes, &grp);
  auto attr = grp->AddUnknownAttribute("attributes-charset", true,
                                       ipp::AttrType::charset);
  attr->SetValue("utf-8");
  attr = grp->AddUnknownAttribute("attributes-natural-language", true,
                                  ipp::AttrType::naturalLanguage);
  attr->SetValue("en-us");
}

struct Converter {
  std::vector<Log> log;
  FrameData frame_data;
  FrameBuilder builder{&frame_data, &log};
  Converter(Version version,
            uint16_t operation_id_or_status_code,
            int32_t request_id,
            const Package* package) {
    frame_data.major_version_number_ = (static_cast<uint16_t>(version) >> 8);
    frame_data.minor_version_number_ = (static_cast<uint16_t>(version) & 0xffu);
    frame_data.operation_id_or_status_code_ = operation_id_or_status_code;
    frame_data.request_id_ = request_id;
    builder.BuildFrameFromPackage(package);
  }
};

}  // namespace

Frame::Frame()
    : version_(static_cast<ipp::Version>(0)),
      operation_id_or_status_code_(0),
      request_id_(0) {}

Frame::Frame(Version ver,
             Operation operation_id,
             int32_t request_id,
             bool set_charset)
    : version_(ver),
      operation_id_or_status_code_(static_cast<uint16_t>(operation_id)),
      request_id_(request_id) {
  if (set_charset) {
    SetCharsetAndLanguageAttributes(this);
  }
}

Frame::Frame(Version ver,
             Status status_code,
             int32_t request_id,
             bool set_charset)
    : version_(ver),
      operation_id_or_status_code_(static_cast<uint16_t>(status_code)),
      request_id_(request_id) {
  if (set_charset) {
    SetCharsetAndLanguageAttributes(this);
  }
}

Frame::Frame(const uint8_t* buffer, size_t size, ParsingResults* result) {
  if (buffer == nullptr) {
    version_ = static_cast<ipp::Version>(0);
    operation_id_or_status_code_ = 0;
    request_id_ = 0;
    if (result != nullptr) {
      result->errors.push_back(Log({"Buffer is nullptr"}));
      result->whole_buffer_was_parsed = false;
    }
    return;
  }
  std::vector<Log> log;
  FrameData frame_data;
  Parser parser(&frame_data, &log);
  const bool completed1 = parser.ReadFrameFromBuffer(buffer, buffer + size);
  const bool completed2 = parser.SaveFrameToPackage(false, &package_);
  if (result) {
    result->whole_buffer_was_parsed = completed1 && completed2;
    result->errors.swap(log);
  }
  uint16_t ver = frame_data.major_version_number_;
  ver <<= 8;
  ver += frame_data.minor_version_number_;
  version_ = static_cast<Version>(ver);
  operation_id_or_status_code_ = frame_data.operation_id_or_status_code_;
  request_id_ = frame_data.request_id_;
}

size_t Frame::GetLength() const {
  std::vector<Log> log;
  FrameData frame_data;
  FrameBuilder builder(&frame_data, &log);
  builder.BuildFrameFromPackage(&package_);
  return builder.GetFrameLength();
}

size_t Frame::SaveToBuffer(uint8_t* buffer, size_t buffer_length) const {
  Converter converter(version_, operation_id_or_status_code_, request_id_,
                      &package_);
  const size_t length = converter.builder.GetFrameLength();
  if (length > buffer_length) {
    return 0;
  }
  converter.builder.WriteFrameToBuffer(buffer);
  return length;
}

std::vector<uint8_t> Frame::SaveToBuffer() const {
  Converter converter(version_, operation_id_or_status_code_, request_id_,
                      &package_);
  std::vector<uint8_t> out(converter.builder.GetFrameLength());
  converter.builder.WriteFrameToBuffer(out.data());
  return out;
}

Version Frame::VersionNumber() const {
  return version_;
}

Version& Frame::VersionNumber() {
  return version_;
}

uint16_t& Frame::OperationIdOrStatusCode() {
  return operation_id_or_status_code_;
}

Operation Frame::OperationId() const {
  return static_cast<Operation>(operation_id_or_status_code_);
}

Status Frame::StatusCode() const {
  return static_cast<Status>(operation_id_or_status_code_);
}

int32_t& Frame::RequestId() {
  return request_id_;
}

int32_t Frame::RequestId() const {
  return request_id_;
}

const std::vector<uint8_t>& Frame::Data() const {
  return package_.Data();
}

std::vector<uint8_t> Frame::TakeData() {
  std::vector<uint8_t> data;
  data.swap(package_.Data());
  return data;
}

Code Frame::SetData(std::vector<uint8_t>&& data) {
  if (data.size() > kMaxPayloadSize) {
    return Code::kDataTooLong;
  }
  std::vector<uint8_t> data2;
  data2.swap(data);
  package_.Data() = std::move(data2);
  return Code::kOK;
}

std::vector<Collection*> Frame::GetGroups(GroupTag tag) {
  std::vector<Collection*> out;
  Group* grp = package_.GetGroup(tag);
  if (grp != nullptr) {
    out.resize(grp->GetSize());
    for (size_t i = 0; i < out.size(); ++i) {
      out[i] = grp->GetCollection(i);
    }
  }
  return out;
}

std::vector<const Collection*> Frame::GetGroups(GroupTag tag) const {
  std::vector<const Collection*> out;
  const Group* grp = package_.GetGroup(tag);
  if (grp != nullptr) {
    out.resize(grp->GetSize());
    for (size_t i = 0; i < out.size(); ++i) {
      out[i] = grp->GetCollection(i);
    }
  }
  return out;
}

Collection* Frame::GetGroup(GroupTag tag, size_t index) {
  Group* grp = package_.GetGroup(tag);
  if (grp != nullptr) {
    return grp->GetCollection(index);
  }
  return nullptr;
}

const Collection* Frame::GetGroup(GroupTag tag, size_t index) const {
  const Group* grp = package_.GetGroup(tag);
  if (grp != nullptr) {
    return grp->GetCollection(index);
  }
  return nullptr;
}

Code Frame::AddGroup(GroupTag tag, Collection** new_group) {
  if (tag < kMinGroupTag || tag > kMaxGroupTag ||
      static_cast<int>(tag) == 0x03) {
    return Code::kInvalidGroupTag;
  }
  auto grp = package_.AddUnknownGroup(tag, true);
  if (grp == nullptr) {
    grp = package_.GetGroup(tag);
    if (grp == nullptr) {
      return Code::kTooManyGroups;
    }
  }
  auto size = grp->GetSize();
  grp->Resize(size + 1);
  if (new_group) {
    *new_group = grp->GetCollection(size);
  }
  return Code::kOK;
}

}  // namespace ipp
