#ifndef _UTILS_H_
#define _UTILS_H_

#include <allegro.h>
#include <stdio.h>
#include "../ma_classfactory.h"

class TMAVectorBase;
class TMAVector;
class TMAVectorOrdered;
class TMAItemComparator;
class TMAString;
class TMAFileReader;
class TMARectangle;
class TMARandom;

typedef TMAVectorBase* PMAVectorBase;
typedef TMAVector* PMAVector;
typedef TMAVectorOrdered* PMAVectorOrdered;
typedef TMAItemComparator* PMAItemComparator;
typedef TMAString* PMAString;
typedef TMAFileReader* PMAFileReader;
typedef TMARectangle* PMARectangle;
typedef TMARandom* PMARandom;

// **************************************************
// Clase que implementa un vector dinamico de objetos
// **************************************************
//
class TMAVectorBase : public TMAObject
{
    REGISTER_CLASS protected:
                
        PMAObject *CItems;
        int ii_ngrow;
        long il_initsize,il_vsize,il_count;
        bool ib_delete_items;
        
        void grow_buffer(bool grow=true);
        void delete_objects();
        void swaps_element(long index1,long index2);
        bool findElement(PMAObject,long&);
        long add_element(PMAObject,long index);   
        
    public:
        PUBLIC_CLASS_ID;
        
        // Crea un vector con una determinada capacidad inicial
        // y con un factor de crecimimento.
        //
        TMAVectorBase(int elems=10,int grow=10,bool delete_items=true);
        virtual ~TMAVectorBase();
        
        // Métodos de manejo de elementos del vector
        //
        void redim(long initsize);
        void fillEmpty(long numelems);
        PMAObject elementAt(long index);
        bool removeElement(PMAObject,bool delobject=true);
        bool removeElementAt(long index,bool delobject=true);
        void clear(void);
        void pack(void);
        long size(void) { return il_count; }
        bool exists(PMAObject);
};

// ******************************
// Clase que implementa un vector 
// ******************************
//
class TMAVector : public TMAVectorBase
{
    REGISTER_CLASS protected:
                
    public:
        PUBLIC_CLASS_ID;
        
        TMAVector(int elems=10,int grow=10,bool delete_items=true):
            TMAVectorBase(elems,grow,delete_items){};
                
        // Métodos de manejo de elementos del vector
        //
        long addElement(PMAObject);
        long addElementAt(PMAObject,long index);
        bool replaceElementAt(PMAObject,long index);
};

// ***************************************
// Clase que implementa un vector ordenado
// ***************************************
//
class TMAVectorOrdered : public TMAVectorBase
{
    REGISTER_CLASS protected:

        PMAItemComparator io_comp;
                
    public:
        PUBLIC_CLASS_ID;
                
        TMAVectorOrdered(PMAItemComparator icomp=NULL,int elems=10,int grow=10,bool delete_items=true);
        ~TMAVectorOrdered();
        
        // Establece el objeto comparador
        //
        void setComparator(PMAItemComparator);
        
        // Inserta un elemento en el vector de forma ordenada
        //
        long addElement(PMAObject);
};

// **************************************************************
// Clase que implementa un interfaz para comparación de elementos
// **************************************************************
//
class TMAItemComparator : public TMAObject
{
    REGISTER_CLASS protected:
                
    public:
        PUBLIC_CLASS_ID;
                 
        // Comparación de dos objetos.
        // Retorna:
        //      -1 -> o1<o2
        //       0 -> o1=o2
        //       1 -> o1>o2
        //
        virtual int compare(TMAObject& o1,TMAObject& o2)=0L;
};

// *****************************
// Clase que encapsula un String
// *****************************
//
class TMAString:public TMAObject
{
    REGISTER_CLASS protected:

        char *Dato;
        int size;
        void clear(void); // Borra el contenido.

    public:
        PUBLIC_CLASS_ID;
        
        ~TMAString ();
        TMAString ();
        TMAString (const TMAString&); // Constructor de Copia por referencia.
        TMAString (const char *);
        
        int length(void) {return size;};
        int findStr(TMAString& Sub);
        TMAString numToStr(long num,int ndig);
        long intValue(void);
        TMAString toUpperCase(void);
        TMAString toLowerCase(void);
        
        TMAString mid(int Index,int numchar);
        TMAString trim(void);
        
        void replaceChar(char origen,char destino);
                
        const char* text(void)  {return Dato;};
        const char* operator *(void) {return Dato;};
        char operator [](int P) {return Dato[P];};
        
        TMAString operator + (const char *);
        TMAString operator + (const TMAString&);
        
        TMAString& operator = (char *);
        TMAString& operator = (TMAString&);
        TMAString& operator = (TMAString);        
        
        int compare(const TMAString&);
};


// **********************************************
// Interfaz para clases que trabajan con ficheros
// **********************************************
//
class TMAFileReader : public TMAObject
{
    REGISTER_CLASS protected:
        
    public:
        PUBLIC_CLASS_ID;
    
        long getCurrentOffset(FILE*);
        bool seekTo(FILE*,long);
        long getBytes(FILE *,void *,long size);
        unsigned char getByte(FILE*);
        unsigned int  get2BWord(FILE*);
        unsigned long get4BWord(FILE*);
        TMAString getString(FILE*,int size);        
    
        virtual bool readFromFile(FILE*)=0L;
};

// ******************
// Clase TMARectangle
// ******************
//
class TMARectangle : public TMAObject
{
    REGISTER_CLASS protected:
        
    public:
        PUBLIC_CLASS_ID;
        int x,y;
        int width,height;
        
        TMARectangle();
        TMARectangle(int px,int py,int w,int h);
        TMARectangle(const TMARectangle& r);
        TMARectangle(int w, int h);
        TMARectangle& operator = (TMARectangle& r);
        TMARectangle& operator = (TMARectangle);
        
        void setBounds(TMARectangle& r);
        void setBounds(int px, int py, int pw, int ph);
        void setLocation(int px, int py);
        void translate(int px, int py);
        void setSize(int pw,int ph);
        bool contains(int px, int py);
        bool intersects(TMARectangle& r);
        TMARectangle intersection(TMARectangle& r);
        TMARectangle unionRect(TMARectangle& r);
        bool isEmpty();        
};

// ***************
// Clase TMARandom
// ***************
//
class TMARandom : public TMAObject
{
    REGISTER_CLASS protected:
        
    public:
        PUBLIC_CLASS_ID;
        
        void init(unsigned long seed=0);
        unsigned long nextInt(void);
        unsigned long nextInt(unsigned long);
};

#endif
