/*
 * Copyright ©2026 Soham Pardeshi. All rights reserved.
 * Permission is hereby granted to students registered for University of
 * Washington CSE 333 for use solely during Summer Quarter 2026 for
 * purposes of the course. No other use, copying, distribution, or
 * modification is permitted without prior written consent. Copyrights
 * for third-party components of this work must be honored. Instructors
 * interested in reusing these course materials should contact the author.
 */

#include "LinkedIntList.h"

#include <memory>

namespace intlist333 {

void LinkedIntList::Push(int payload) {
  auto new_node = std::make_shared<Node>();
  new_node->payload = payload;
  new_node->next = head_;

  if (new_node->next == nullptr) {
    tail_ = new_node;
  } else {
    new_node->next->prev = new_node;
  }

  head_ = new_node;
  ++num_elements_;
}

void LinkedIntList::Append(int payload) {
  auto new_node = std::make_shared<Node>();
  new_node->payload = payload;
  new_node->prev = tail_;

  if (head_ == nullptr) {
    head_ = new_node;
  } else {
    tail_.lock()->next = new_node;
  }

  tail_ = new_node;
  ++num_elements_;
}

bool LinkedIntList::Pop(int* const payload_ptr) {
  if (head_ == nullptr) {
    return false;
  }

  *payload_ptr = head_->payload;
  head_ = head_->next;
  if (head_ == nullptr) {
    tail_.reset();
  } else {
    head_->prev.reset();
  }
  --num_elements_;
  return true;
}

bool LinkedIntList::Slice(int* const payload_ptr) {
  std::shared_ptr<Node> old_tail = tail_.lock();
  if (old_tail == nullptr) {
    return false;
  }

  *payload_ptr = old_tail->payload;
  if (old_tail->prev.expired()) {
    head_.reset();
    tail_.reset();
  } else {
    tail_ = old_tail->prev;
    tail_.lock()->next.reset();
  }
  --num_elements_;
  return true;
}

}  // namespace intlist333