// Copyright (c) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SOURCE_UTIL_ILIST_H_
#define SOURCE_UTIL_ILIST_H_

#include <cassert>
#include <memory>
#include <type_traits>
#include <vector>

#include "source/util/ilist_node.h"

namespace spvtools {
namespace utils {

// An IntrusiveList is a generic implementation of a doubly-linked list.  The
// intended convention for using this container is:
//
//      class Node : public IntrusiveNodeBase<Node> {
//        // Note that "Node", the class being defined is the template.
//        // Must have a default constructor accessible to List.
//        // Add whatever data is needed in the node
//      };
//
//      using List = IntrusiveList<Node>;
//
// You can also inherit from IntrusiveList instead of a typedef if you want to
// add more functionality.
//
// The condition on the template for IntrusiveNodeBase is there to add some type
// checking to the container.  The compiler will still allow inserting elements
// of type IntrusiveNodeBase<Node>, but that would be an error. This assumption
// allows NextNode and PreviousNode to return pointers to Node, and casting will
// not be required by the user.

template <class NodeType>
class IntrusiveList {
 public:
  static_assert(
      std::is_base_of<IntrusiveNodeBase<NodeType>, NodeType>::value,
      "The type from the node must be derived from IntrusiveNodeBase, with "
      "itself in the template.");

  // Creates an empty list.
  inline IntrusiveList();

  // Moves the contents of the given list to the list being constructed.
  IntrusiveList(IntrusiveList&&);

  // Destorys the list.  Note that the elements of the list will not be deleted,
  // but they will be removed from the list.
  virtual ~IntrusiveList();

  // Moves all of the elements in the list on the RHS to the list on the LHS.
  IntrusiveList& operator=(IntrusiveList&&);

  // Basetype for iterators so an IntrusiveList can be traversed like STL
  // containers.
  template <class T>
  class iterator_template {
   public:
    iterator_template(const iterator_template& i) : node_(i.node_) {}

    iterator_template& operator++() {
      node_ = node_->next_node_;
      return *this;
    }

    iterator_template& operator--() {
      node_ = node_->previous_node_;
      return *this;
    }

    iterator_template& operator=(const iterator_template& i) {
      node_ = i.node_;
      return *this;
    }

    T& operator*() const { return *node_; }
    T* operator->() const { return node_; }

    friend inline bool operator==(const iterator_template& lhs,
                                  const iterator_template& rhs) {
      return lhs.node_ == rhs.node_;
    }
    friend inline bool operator!=(const iterator_template& lhs,
                                  const iterator_template& rhs) {
      return !(lhs == rhs);
    }

    // Moves the nodes in |list| to the list that |this| points to.  The
    // positions of the nodes will be immediately before the element pointed to
    // by the iterator.  The return value will be an iterator pointing to the
    // first of the newly inserted elements.
    iterator_template MoveBefore(IntrusiveList* list) {
      if (list->empty()) return *this;

      NodeType* first_node = list->sentinel_.next_node_;
      NodeType* last_node = list->sentinel_.previous_node_;

      this->node_->previous_node_->next_node_ = first_node;
      first_node->previous_node_ = this->node_->previous_node_;

      last_node->next_node_ = this->node_;
      this->node_->previous_node_ = last_node;

      list->sentinel_.next_node_ = &list->sentinel_;
      list->sentinel_.previous_node_ = &list->sentinel_;

      return iterator(first_node);
    }

    // Define standard iterator types needs so this class can be
    // used with <algorithms>.
    using iterator_category = std::bidirectional_iterator_tag;
    using difference_type = std::ptrdiff_t;
    using value_type = T;
    using pointer = T*;
    using const_pointer = const T*;
    using reference = T&;
    using const_reference = const T&;
    using size_type = size_t;

   protected:
    iterator_template() = delete;
    inline iterator_template(T* node) { node_ = node; }
    T* node_;

    friend IntrusiveList;
  };

  using iterator = iterator_template<NodeType>;
  using const_iterator = iterator_template<const NodeType>;

  // Various types of iterators for the start (begin) and one past the end (end)
  // of the list.
  //
  // Decrementing |end()| iterator will give and iterator pointing to the last
  // element in the list, if one exists.
  //
  // Incrementing |end()| iterator will give |begin()|.
  //
  // Decrementing |begin()| will give |end()|.
  //
  // TODO: Not marking these functions as noexcept because Visual Studio 2013
  // does not support it.  When we no longer care about that compiler, we should
  // mark these as noexcept.
  iterator begin();
  iterator end();
  const_iterator begin() const;
  const_iterator end() const;
  const_iterator cbegin() const;
  const_iterator cend() const;

  // Appends |node| to the end of the list.  If |node| is already in a list, it
  // will be removed from that list first.
  void push_back(NodeType* node);

  // Returns true if the list is empty.
  bool empty() const;

  // Makes the current list empty.
  inline void clear();

  // Returns references to the first or last element in the list.  It is an
  // error to call these functions on an empty list.
  NodeType& front();
  NodeType& back();
  const NodeType& front() const;
  const NodeType& back() const;

  // Transfers [|first|, |last|) from |other| into the list at |where|.
  //
  // If |other| is |this|, no change is made.
  void Splice(iterator where, IntrusiveList<NodeType>* other, iterator first,
              iterator last);

 protected:
  // Doing a deep copy of the list does not make sense if the list does not own
  // the data.  It is not clear who will own the newly created data.  Making
  // copies illegal for that reason.
  IntrusiveList(const IntrusiveList&) = delete;
  IntrusiveList& operator=(const IntrusiveList&) = delete;

  // This function will assert if it finds the list containing |node| is not in
  // a valid state.
  static void Check(NodeType* node);

  // A special node used to represent both the start and end of the list,
  // without being part of the list.
  NodeType sentinel_;
};

// Implementation of IntrusiveList

template <class NodeType>
inline IntrusiveList<NodeType>::IntrusiveList() : sentinel_() {
  sentinel_.next_node_ = &sentinel_;
  sentinel_.previous_node_ = &sentinel_;
  sentinel_.is_sentinel_ = true;
}

template <class NodeType>
IntrusiveList<NodeType>::IntrusiveList(IntrusiveList&& list) : sentinel_() {
  sentinel_.next_node_ = &sentinel_;
  sentinel_.previous_node_ = &sentinel_;
  sentinel_.is_sentinel_ = true;
  list.sentinel_.ReplaceWith(&sentinel_);
}

template <class NodeType>
IntrusiveList<NodeType>::~IntrusiveList() {
  clear();
}

template <class NodeType>
IntrusiveList<NodeType>& IntrusiveList<NodeType>::operator=(
    IntrusiveList<NodeType>&& list) {
  list.sentinel_.ReplaceWith(&sentinel_);
  return *this;
}

template <class NodeType>
inline typename IntrusiveList<NodeType>::iterator
IntrusiveList<NodeType>::begin() {
  return iterator(sentinel_.next_node_);
}

template <class NodeType>
inline typename IntrusiveList<NodeType>::iterator
IntrusiveList<NodeType>::end() {
  return iterator(&sentinel_);
}

template <class NodeType>
inline typename IntrusiveList<NodeType>::const_iterator
IntrusiveList<NodeType>::begin() const {
  return const_iterator(sentinel_.next_node_);
}

template <class NodeType>
inline typename IntrusiveList<NodeType>::const_iterator
IntrusiveList<NodeType>::end() const {
  return const_iterator(&sentinel_);
}

template <class NodeType>
inline typename IntrusiveList<NodeType>::const_iterator
IntrusiveList<NodeType>::cbegin() const {
  return const_iterator(sentinel_.next_node_);
}

template <class NodeType>
inline typename IntrusiveList<NodeType>::const_iterator
IntrusiveList<NodeType>::cend() const {
  return const_iterator(&sentinel_);
}

template <class NodeType>
void IntrusiveList<NodeType>::push_back(NodeType* node) {
  node->InsertBefore(&sentinel_);
}

template <class NodeType>
bool IntrusiveList<NodeType>::empty() const {
  return sentinel_.NextNode() == nullptr;
}

template <class NodeType>
void IntrusiveList<NodeType>::clear() {
  while (!empty()) {
    front().RemoveFromList();
  }
}

template <class NodeType>
NodeType& IntrusiveList<NodeType>::front() {
  NodeType* node = sentinel_.NextNode();
  assert(node != nullptr && "Can't get the front of an empty list.");
  return *node;
}

template <class NodeType>
NodeType& IntrusiveList<NodeType>::back() {
  NodeType* node = sentinel_.PreviousNode();
  assert(node != nullptr && "Can't get the back of an empty list.");
  return *node;
}

template <class NodeType>
const NodeType& IntrusiveList<NodeType>::front() const {
  NodeType* node = sentinel_.NextNode();
  assert(node != nullptr && "Can't get the front of an empty list.");
  return *node;
}

template <class NodeType>
const NodeType& IntrusiveList<NodeType>::back() const {
  NodeType* node = sentinel_.PreviousNode();
  assert(node != nullptr && "Can't get the back of an empty list.");
  return *node;
}

template <class NodeType>
void IntrusiveList<NodeType>::Splice(iterator where,
                                     IntrusiveList<NodeType>* other,
                                     iterator first, iterator last) {
  if (first == last) return;
  if (other == this) return;

  NodeType* first_prev = first.node_->previous_node_;
  NodeType* where_next = where.node_->next_node_;

  // Attach first.
  where.node_->next_node_ = first.node_;
  first.node_->previous_node_ = where.node_;

  // Attach last.
  where_next->previous_node_ = last.node_->previous_node_;
  last.node_->previous_node_->next_node_ = where_next;

  // Fixup other.
  first_prev->next_node_ = last.node_;
  last.node_->previous_node_ = first_prev;
}

template <class NodeType>
void IntrusiveList<NodeType>::Check(NodeType* start) {
  int sentinel_count = 0;
  NodeType* p = start;
  do {
    assert(p != nullptr);
    assert(p->next_node_->previous_node_ == p);
    assert(p->previous_node_->next_node_ == p);
    if (p->is_sentinel_) sentinel_count++;
    p = p->next_node_;
  } while (p != start);
  assert(sentinel_count == 1 && "List should have exactly 1 sentinel node.");

  p = start;
  do {
    assert(p != nullptr);
    assert(p->previous_node_->next_node_ == p);
    assert(p->next_node_->previous_node_ == p);
    if (p->is_sentinel_) sentinel_count++;
    p = p->previous_node_;
  } while (p != start);
}

}  // namespace utils
}  // namespace spvtools

#endif  // SOURCE_UTIL_ILIST_H_
