// 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.

#ifndef LIBIPP_IPP_PACKAGE_H_
#define LIBIPP_IPP_PACKAGE_H_

#include "ipp_attribute.h"
#include "ipp_enums.h"
#include "ipp_export.h"

#include <cstdint>
#include <map>
#include <string>
#include <vector>

namespace ipp {

class Group;

// This class represents IPP frame. It is container for Groups that represent
// IPP attributes groups (like operation-attributes). Groups in a single Package
// must have unique tags (names).
class IPP_EXPORT Package {
 public:
  // destructor
  virtual ~Package();

  // Returns vector of all groups in the package, all pointers are != nullptr.
  // Returned vector = GetKnownGroups() + vector with unknown groups.
  std::vector<Group*> GetAllGroups();
  std::vector<const Group*> GetAllGroups() const;

  // Returns pointer to the group with given tag.
  // Returns nullptr if there is no group with given tag in the package.
  Group* GetGroup(GroupTag);
  const Group* GetGroup(GroupTag) const;

  // Adds a new group to the package and returns pointer to it or nullptr if
  // a group with given tag already exists in the package.
  Group* AddUnknownGroup(GroupTag, bool is_a_set);

  // Returns reference to payload (e.g. document to print), empty vector means
  // no payload.
  std::vector<uint8_t>& Data() { return data_; }
  const std::vector<uint8_t>& Data() const { return data_; }

 protected:
  Package() = default;

 private:
  // Copy/move/assign constructors/operators are not available.
  Package(const Package&) = delete;
  Package(Package&&) = delete;
  Package& operator=(const Package&) = delete;
  Package& operator=(Package&&) = delete;

  // Returns vector with groups in the schema, all pointers are != nullptr.
  // This method must be overloaded in derived classes with schema.
  virtual std::vector<Group*> GetKnownGroups() { return {}; }
  virtual std::vector<const Group*> GetKnownGroups() const { return {}; }

  std::vector<Group*> unknown_groups_;
  std::vector<uint8_t> data_;
};

// Defined later in this file.
class Collection;

// Base class represents single IPP attribute group or a sequence of the
// same IPP attribute groups. Single instance of IPP attribute groups is
// represented by Collection object.
class IPP_EXPORT Group {
 public:
  virtual ~Group() { Resize(0); }

  // Returns tag of the group.
  GroupTag GetName() const { return name_; }

  // Returns true if it is a sequence of IPP groups (Collections) or false
  // if it is a single IPP group (one Collection).
  bool IsASet() const { return is_a_set_; }

  // Returns the current number of elements (IPP groups) in the Group.
  // (IsASet() == false) => always returns 1.
  size_t GetSize() const { return groups_.size(); }

  // Resizes a sequence of IPP groups.
  // Does nothing if (IsASet() == false) and (|new_size| > 1).
  void Resize(size_t new_size) {
    if (!is_a_set_ && new_size > 1)
      return;
    while (new_size < groups_.size()) {
      delete groups_.back();
      groups_.pop_back();
    }
    while (new_size > groups_.size()) {
      groups_.push_back(CreateCollection());
    }
  }

  // Returns a pointer to underlying collection, representing one of the IPP
  // groups. Returns nullptr <=> (index >= GetSize()).
  Collection* GetCollection(size_t index = 0) {
    if (index >= groups_.size())
      return nullptr;
    return groups_[index];
  }
  const Collection* GetCollection(size_t index = 0) const {
    if (index >= groups_.size())
      return nullptr;
    return groups_.at(index);
  }

 protected:
  Group(GroupTag name, bool is_a_set) : name_(name), is_a_set_(is_a_set) {}

 private:
  virtual Collection* CreateCollection() = 0;
  GroupTag name_;
  bool is_a_set_;
  std::vector<Collection*> groups_;
};

// Final class for Groups, represents Group with single IPP attribute group
// defined in the schema. Template parameter TCollection must be a class
// derived from Collection and defines the structure of the group.
template <class TCollection>
class SingleGroup : public Group {
 public:
  explicit SingleGroup(GroupTag name) : Group(name, false) {}
  // Allows to refer to fields in the underlying collection.
  // Creates the collection if it not exists.
  TCollection* operator->() {
    Resize(1);
    return dynamic_cast<TCollection*>(GetCollection());
  }
  // Returns reference to the underlying collection. If the group is empty
  // (GetSize() == 0) returns a reference to an empty static collection.
  const TCollection& Get() const {
    const Collection* coll = GetCollection();
    if (coll == nullptr)
      return TCollection::empty;
    return *(dynamic_cast<const TCollection*>(coll));
  }

 private:
  Collection* CreateCollection() override { return new TCollection; }
};

// Final class for Group, represents sequence of IPP attribute groups with
// the same tag and defined in the schema. Template parameter TCollection is
// a class derived from Collection and defines the structure of a single group.
template <class TCollection>
class SetOfGroups : public Group {
 public:
  explicit SetOfGroups(GroupTag name) : Group(name, true) {}
  // If |index| is out of range, the vector is resized to (index+1).
  TCollection& operator[](size_t index) {
    if (GetSize() <= index)
      Resize(index + 1);
    return *(dynamic_cast<TCollection*>(GetCollection(index)));
  }
  // Const version of the method above. If |index| is out of range,
  // a reference to an empty static collection is returned.
  const TCollection& At(size_t index) const {
    const Collection* coll = GetCollection(index);
    if (coll == nullptr)
      return TCollection::empty;
    return *(dynamic_cast<const TCollection*>(coll));
  }

 private:
  Collection* CreateCollection() override { return new TCollection; }
};

// Final class for Group, represents Group not defined in the schema.
class UnknownGroup : public Group {
 public:
  UnknownGroup(GroupTag name, bool is_a_set) : Group(name, is_a_set) {}

 private:
  Collection* CreateCollection() override { return new EmptyCollection; }
};

}  // namespace ipp

#endif  //  LIBIPP_IPP_PACKAGE_H_
