// @topic T060930 Stack of integers v4
// @brief Stack class implementation with copy constructor and destructor

#include "Stack.h"

// default constructor
Stack::Stack()
{
    std::cout << __FUNCTION__ << " default\n";
    stack_memory = new int[ DEFAULT_CAPACITY ];
    capacity = DEFAULT_CAPACITY;
    top_pos = 0;
}

// specific constructor
Stack::Stack( int initial_capacity )
{
    std::cout << __FUNCTION__ << " capacity\n";
    stack_memory = new int[initial_capacity];
    capacity = initial_capacity;
    top_pos = 0;
}

// copy constructor
Stack::Stack(Stack const& other)
{
    std::cout << __FUNCTION__ << " copy\n";
    stack_memory = new int[other.capacity];
    for (int idx = 0; idx < other.size(); ++idx) {
        stack_memory[idx] = other.stack_memory[idx];
    }
    capacity = other.capacity;
    top_pos = other.top_pos;
}

// move constructor
Stack::Stack(Stack&& other)
{
    std::cout << __FUNCTION__ << " move\n";
    stack_memory = other.stack_memory;
    capacity = other.capacity;
    top_pos = other.top_pos;
    other.stack_memory = nullptr;
}

// initializer list constructor
Stack::Stack(std::initializer_list<int> list)
{
    capacity = 2 * list.size();
    stack_memory = new int[capacity];
    top_pos = list.size();
    std::copy( list.begin(), list.end(), stack_memory );
}

// overloaded assignment operator
Stack& Stack::operator= (Stack const& other)
{
    if (this == &other) {
        // guard against self-assignment
        return *this;
    }
    delete[] stack_memory;
    stack_memory = new int[other.capacity];
    for (int idx = 0; idx < other.size(); ++idx) {
        stack_memory[idx] = other.stack_memory[idx];
    }
    capacity = other.capacity;
    top_pos = other.top_pos;
    return *this;
}


Stack::~Stack()
{
    std::cout << __FUNCTION__ << "\n";
    delete[] stack_memory;
}

void Stack::push( int value )
{
    stack_memory[top_pos] = value;
    ++top_pos;
}

void Stack::pop()
{
    --top_pos;
}

int Stack::top() const
{
    return stack_memory[ top_pos ];
}

int& Stack::top()
{
    return stack_memory[ top_pos ];
}

int Stack::size() const
{
    return top_pos;
}