/*###Begin banned keyword - each of the following line if appear in code will raise error. regex supported
define
include
using
###End banned keyword*/

#include  <iostream>
using namespace std;

struct DNode
{
	int info;
	DNode *pNext, *pPrev;
};

struct DList
{
	DNode *pHead, *pTail;
};


void init(DList &L)
{
    L.pHead = L.pTail = NULL;
}

void createList(DList &L)
{
    int x;
    cin >> x;
    while (x != -1)
    {
        DNode *p = new DNode;
        p->info = x;
        p->pNext = NULL;
        p->pPrev = NULL;

        if (L.pHead == NULL)
        {
            L.pHead = L.pTail = p;
        }
        else
        {
            L.pTail->pNext = p;
            p->pPrev = L.pTail;
            L.pTail = p;
        }

        cin >> x;
    }
}

void printList(DList L)
{
    DNode *p = L.pHead;
    while (p != NULL)
    {
        cout << p->info << " ";
        p = p->pNext;
    }
    cout << endl;
}

void addHead(DList &L, int x)
{
    DNode *p = new DNode;
    p->info = x;
    p->pNext = L.pHead;
    p->pPrev = NULL;

    if (L.pHead == NULL)
    {
        L.pHead = L.pTail = p;
    }
    else
    {
        L.pHead->pPrev = p;
        L.pHead = p;
    }
}

void addTail(DList &L, int x)
{
    DNode *p = new DNode;
    p->info = x;
    p->pNext = NULL;
    p->pPrev = L.pTail;

    if (L.pHead == NULL)
    {
        L.pHead = L.pTail = p;
    }
    else
    {
        L.pTail->pNext = p;
        L.pTail = p;
    }
}

void addAfter(DList &L, int x, int y)
{
    DNode *p = L.pHead;
    while (p != NULL && p->info != x)
    {
        p = p->pNext;
    }

    if (p != NULL)
    {
        DNode *q = new DNode;
        q->info = y;
        q->pNext = p->pNext;
        q->pPrev = p;

        if (p->pNext != NULL)
        {
            p->pNext->pPrev = q;
        }
        else
        {
            L.pTail = q;
        }

        p->pNext = q;
    }
}

void addBefore(DList &L, int x, int y)
{
    DNode *p = L.pHead;
    while (p != NULL && p->info != x)
    {
        p = p->pNext;
    }

    if (p != NULL)
    {
        DNode *q = new DNode;
        q->info = y;
        q->pNext = p;
        q->pPrev = p->pPrev;

        if (p->pPrev != NULL)
        {
            p->pPrev->pNext = q;
        }
        else
        {
            L.pHead = q;
        }

        p->
pPrev = q;
}
}

void addAfterMulti(DList &L, int x, int y)
{
DNode *p = L.pHead;
while (p != NULL)
{
if (p->info == x)
{
DNode *q = new DNode;
q->info = y;
q->pNext = p->pNext;
q->pPrev = p;
        if (p->pNext != NULL)
        {
            p->pNext->pPrev = q;
        }
        else
        {
            L.pTail = q;
        }

        p->pNext = q;
    }

    p = p->pNext;
}
}

void addBeforeMulti(DList &L, int x, int y)
{
DNode *p = L.pHead;
while (p != NULL)
{
if (p->info == x)
{
DNode *q = new DNode;
q->info = y;
q->pNext = p;
q->pPrev = p->pPrev;

        if (p->pPrev != NULL)
        {
            p->pPrev->pNext = q;
        }
        else
        {
            L.pHead = q;
        }

        p->pPrev = q;
    }

    p = p->pNext;
}
}

void removeHead(DList &L)
{
    if (L.pHead==NULL)
    {
        cout<<"\nList is empty. Can't delete";
    }
    else
    {
        cout<<"\nDo you want to delete the first element?(y/n): ";
        char x;
        cin>>x;
        if (x=='Y' || x=='y')
        {
            if (L.pHead==L.pTail)
            {
                L.pHead = NULL;
                L.pTail = NULL;
                cout<<"\nThe list becomes empty";
            }
            else
            {
                DNode *p=L.pHead;
                L.pHead=L.pHead->pNext;
                L.pHead->pPrev=NULL;
                p->pNext=NULL;
                delete p;
            }
        }
        else return;
    }
}
void removeTail(DList &L)
{
    if (L.pHead==NULL)
    {
        cout<<"\nList is empty. Can't delete";
    }
    else
    {
        cout<<"\nDo you want to delete the last element?(y/n): ";
        char x;
        cin>>x;
        if (x=='Y' || x=='y')
        {
            if (L.pHead==L.pTail)
            {
                L.pHead=L.pTail=NULL;
                cout<<"\nThe list becomes empty";
            }
            else
            {
                DNode *p=L.pTail;
                L.pTail=L.pTail->pPrev;
                L.pTail->pNext=NULL;
                p->pPrev=NULL;
                delete p;
            }    
        }
        else return;
    }   
}
int main()
{
	DList L;
	init(L);
	int x,y,choice; char c;

	cout<<"MENU:";
    cout<<"\n1. Create a DList";
    cout<<"\n2. Print the DList";
    cout<<"\n3. Insert a value at the front";
    cout<<"\n4. Insert a value at the end";
    cout<<"\n5. Insert a value after a given value (only for the first value found)";
    cout<<"\n6. Insert a value before a given value (only for the first value found)";
    cout<<"\n7. Insert a value after a given value (for all the same values)";
    cout<<"\n8. Insert a value before a given value (for all the same values)";
    cout<<"\n9. Delete the first element";
    cout<<"\n10. Delete the last element";
    cout<<"\n20. Exit"<<endl;

	while(true)
    {
        cout<<"\n\t\tPLEASE SELECT YOUR CHOICE: ";
        cin>>choice;
        switch(choice)
        {
        case 1:
            cout<<"\nEnter your positive integers until you enter -1 to finish: ";
            createList(L);
            break;
        case 2:
            cout<<"\nYour current DList: ";
            printList(L);
            break;
        case 3:
            cout<<"\nEnter a number: ";
            cin>>x;
            addHead(L,x);
            break;
        case 4:
            cout<<"\nEnter a number: ";
            cin>>x;
            addTail(L,x);
            break;
        case 5:
            cout<<"\nEnter two numbers: ";
            cin>>x>>y;
            addAfter(L,x,y);
            break;
        case 6:
            cout<<"\nEnter two numbers: ";
            cin>>x>>y;
            addBefore(L,x,y);
            break;
        case 7:
            cout<<"\nEnter two numbers: ";
            cin>>x>>y;
            addAfterMulti(L,x,y);
            break;
        case 8:
            cout<<"\nEnter two numbers: ";
            cin>>x>>y;
            addBeforeMulti(L,x,y);
            break;
        case 9:
            removeHead(L);
            break;
        case 10:
            removeTail(L);
            break;
        case 20:
            cout<<"\nGOOD BYE";
            return 0;

        }
    }

	return 0;
}
make it runable with all test case