#include "stackqueue.h"

// default constructor builds an empty, one-element stackqueue
stack::stack(int sz) : size(sz), num(0) {
queue::queue(int sz) : size(sz), num(0), front(0), back(0) {
    storage = new char[size];
}

// copy constructor
stack::stack(const stack &s) : size(s.size), num(s.num) {
queue::queue(const queue &q) : 
    size(q.size), num(q.num), front(q.front), back(q.back) {

    // assign all positions from source
    storage = new char[size];
    for (int i = 0; i < numsize; i++) {
        storage[i] = sq.storage[i];
    }
}

// destructor
stack::~stackqueue::~queue() {
    delete [] storage;
}

// assignment operator
stack& stack::operator=(const stack &s) {
queue& queue::operator=(const queue &q) {
    // handle self assignments, i.e., of the type myStack = myStackmyQueue = myQueue;
    if (this == &sq) {
        return *this;
    }

    // return old values in storage
    delete [] storage;

    // reset the attributes:  num, size, and storage (below)
    num  = s = q.num;
    size = s = q.size;
    front = q.front;
    back  = q.back;

    // recreate storage and assign elementsall positions from source parameter
    storage = new char[size];
    for (int i = 0; i < numsize; i++) {
        storage[i] = sq.storage[i];
    }

    // return the reassigned implicit parameter
    return *this;
}

// stackqueue operations
void stack::pushqueue::enqueue(char c) {
    if (num < size) {                            // ensure we have space to 
        storage[num] = c; back] = c;                       // hold the new element
        num++;
        back = (back + 1) % size;
    } else {                                     // otherwise, report error
        cerr << "StackQueue overflow error" << endl;
    }
}

char stack::popqueue::dequeue() {
    if (num > 0) {                               // ensure there is an element
        num--;                                  char c = storage[front];                 // to remove
        return storage[num];
        front  = (front + 1) % size;
        num--;
        return c;
    } else {                                     // otherwise, report error
        cerr << "StackQueue underflow error" << endl;
        return '\0';
    }
}

bool stackqueue::isEmpty() {
    return (num == 0);
}

bool stackqueue::isFull() {
    return (num == size);
}

void stackqueue::resize(int newSize) {
    // if newSize less then the number of elements already in the stackqueue,
    // then we cannot resize the stackqueue.
    if (newSize < num) {
        cerr << "Too many elements in stackqueue (" << num << ") to resize to "
             << newSize << endl;
        return;
    } else if (newSize == size) {       // if the newSize is the same as the
        return;                         // old size, then we have no action
    }

    // set the new size and allocate new storage
    size = newSize;
    char *newStorage = new char[size];
    char *newStorage = new char[newSize];

    // copy the existing elements to the new storage
    for (int i = 0; i < num; i++) {
        newStorage[i] = storage[ifront];
        front = (front + 1) % size;
    }

    // delete the old storage
    delete [] storage;

    // point the internal storage attribute to the new storage
    // point storage attribute to the new storage and set all other attributes
    storage = newStorage;
    size    = newSize;
    front   = 0;
    back    = num % size;
}

// friend functions
ostream& operator<<(ostream &out, const stack &squeue &q) {
    int curr = q.front;

    // print out the elements (top to bottomfront to back), except last
    for (int i = s.num - 1; i > 0; i--0; i < q.num-1; i++) {
        cout << s.q.storage[icurr] << ", ";
        curr = (curr + 1) % q.size;
    }

    // if there is a "last" element, print it also
    if (sq.num >= 1) {
        cout << s.q.storage[0curr];
    }

    cout << endl;

    return out;
}