// Prof Simão - DAINF/UTFPR - Ctba - TecProg S71 - 1 Sem 2025 - 1a Parcial
// Hah couts e elses suplementares para fins de entendimento da execução.

#include <list>
//#include <vector>
#include <iostream>
using namespace std;

#include <stdlib.h>
#include <time.h>

void semente()
{
    time_t t;                   // https://pt.wikipedia.org/wiki/Time_t
    srand((unsigned) time(&t)); // Para função srand e rand vide: https://www.tutorialspoint.com/c_standard_library/c_function_srand.htm
}

class Animal
{
    private:
        int forca;

    public:

        Animal(const int f = 0):forca (f) { semente(); }
        virtual ~Animal() { forca = -1; }

        virtual const int getForca() const { return forca;} // virtual apenas porque o enunciado manda...

        void operator--() { forca--; }
        void operator++() { forca++; }

        virtual void executar() = 0;
};

class Formiga : public Animal
{
    private:
        bool ferrao;

    public:

        Formiga(const int f = 0):
            Animal(f),
            ferrao(!(rand()%10) )
        {
            semente();
        }

        ~Formiga() { }

        void setFerrao(const bool f) { ferrao = f; } // até o implementei mas não é usado finalmente...
        const bool getFerrao() const { return ferrao; }

        void executar()
        {
            (rand()%10)<6 ? operator++() : operator--();
        }
};

class Formigal
{
    private:
        //vector<Formiga*> forms;
        //vector<Formiga*>::iterator it;
        list<Formiga*> forms;
        list<Formiga*>::iterator it;

    public:

        Formigal() : forms(), it()
        {
            semente();
            forms.clear();
            primeiro();
        }

        ~Formigal()
        {
            for (it=forms.begin(); it != forms.end(); it++)
            {
                if (*it)
                {
                    cout << "Deletando formiga: " << *it << endl;
                    delete *it;
                    *it = NULL;
                }
                else
                {
                    cerr << "Iterador apontando para elemento nulo: " << endl;
                }
            }
            forms.clear();
        }

        void primeiro()
        {
            it = forms.begin();
        }

        void operator++()
        {
            if (!ultimo()) { it++; } else { cerr << "Passou do final de forms em Formigal!" << endl; }
        }

        Formiga* atual() const
        {
            if (!forms.empty())
                return *it;
            else
                return NULL;
        }

        void eliminar()
        {
            if (!forms.empty())
            {
                if (*it)
                {
                    delete *it;
                    *it = NULL;
                }
                else
                {
                    cerr << "Ponteiro de formiga nulo em formigal! " << endl;
                }
                forms.erase(it);
                //forms.remove(*it);

            }
            else
            {
                cerr << "Forms vazio! " << endl;
            }
        }

        const bool ultimo() const // interpretei o último como o fim efetivo...
        {
            //if (it == forms.end()) { return true; } else { return false; }
            return (it == forms.end());
        }

        void incluir(Formiga* p)
        {
            if (p) { forms.push_back(p); }
            else { cerr << "Ponteiro nulo - sem inclusão!" << endl; }
        }

        void executar()
        {
            for ( it = forms.begin(); it != forms.end(); it++)
            {
                if (*it)
                {
                    //cout << endl;
                    (*it)->executar();
                }
                else
                {
                    cerr << "Ponteiro nulo no conjunto" << endl;
                }
            }
            cout << endl;

            primeiro();
        }
};

class Tamandua : public Animal
{
    private:
        Formigal* pForms;

    public:

        Tamandua(const int f = 0): Animal(f), pForms(NULL)
        {
            semente();
        }

        ~Tamandua() { pForms = NULL; }

        void setForms(Formigal* pF) { pForms = pF; }
        //pForms* getForms() const { return pForms; }

        void executar()
        {
            if (!pForms) { cerr << "pForms nulo!" << endl; return; }

            const int max = 100;

            pForms->primeiro();

            Formiga* pF = NULL;

            cout << "Em vias de entrar no loop. " << endl;

            int cont = 1;

            while (pForms->ultimo()!= true)
            {
                cout << "Agora já no loop " << endl;

                pF = NULL;
                pF = pForms->atual();

                if ( pF )
                {
                    if  (   ( pF->getFerrao() == false ) ||
                            ( pF->getForca() < max )
                        )
                    {
                        operator++();
                        cout    << cont << " Formiga neutralizada: " << pForms
                                << " ferrão: " << pF->getFerrao()
                                << " força:  " << pF->getForca()
                                << endl;
                        pForms->eliminar();
                    }
                    else
                    {
                        cout    << cont << " Formiga sobrevivente: " << pForms
                                << " ferrão: " << pF->getFerrao()
                                << " força:  " << pF->getForca()
                                << endl;
                        //pForms->operator++(); // se for vector
                    }
                }
                else
                {
                    cerr << cont << " Ponteiro de formiga nulo!" << endl;
                    //pForms->operator++(); // se for vector
                }
                //cont++;
                pForms->operator++(); // se for list
            }

            cout << "Depois do loop!" << endl;

            pForms->primeiro();
        }
};

class Habitat
{
    private:
        Formigal* pForms;
        Tamandua* pTaman;

        const int maxforms;
        int contforms;

    public:

        Habitat():
            pForms(NULL),
            pTaman(NULL),
            maxforms(20),
            contforms(10)
        {
            semente();

            criarAnimais();
            executar();
        }

        ~Habitat()
        {
            if (pForms)
            {
                delete pForms;
                pForms = NULL;
            }

            if (pTaman)
            {
                delete pTaman;
                pTaman = NULL;
            }
        }

    private:

        void criarAnimais()
        {
            pForms = new Formigal();

            if (!pForms)
            {
                cout << "Formigal Nulo!" << endl;
                return;
            }

            //system("Pause");
            //pForms->operator++();
            //pForms->eliminar();
            //system("Pause");

            pTaman = new Tamandua(contforms);

            if (pTaman)
            {
                 contforms+=10;
                 pTaman->setForms(pForms);
            }
            else
            {
                cerr << "Tamanduá Nulo!" << endl;
                return;
            }

            Formiga* pFormiga = NULL;

            for (int i = 0; i < maxforms; i++)
            {
                pFormiga = new Formiga(contforms);

                if (pFormiga)
                {
                    contforms+=10;
                    pForms->incluir(pFormiga);
                    cout << "Formiga alocada e incluida no FORMIGAL!" << endl;
                }
                else
                {
                    cerr << "Formiga não alocada!" << endl;
                }
                pFormiga = NULL;
            }
            system("pause");
        }


        void executar()
        {
            if (pForms)
            {
                pForms->executar();
            }
            else
            {
                cerr << "pForms nulo!" << endl;
            }

            cout << endl;

            if (pTaman)
            {
                pTaman->executar();
                cout << "A força do Tamanduá é: " << pTaman->getForca() << endl;
            }
            else
            {
                cerr << "pForms nulo!" << endl;
            }
            cout << endl;

            if (pForms)
            {
                int cont = 0;
                pForms->primeiro();
                while (pForms->ultimo()==false)
                {
                    cont++;
                    pForms->operator++();
                }
                cout << "A quantia de formigas sobreviventes é: " << cont << endl;
            }
            else
            {
                cerr << "pForms nulo!" << endl;
            }
        }
};

int main()
{
    semente();

    Habitat habitat;

    cout << endl;
    cout << "FIM" << endl;

    return 0;
}

