// TSList.h: interface for the base class: TSList,
//    inherited classes: TSRecordList, TSTreeList, and TSFieldList, and
//    associated class: TSPosition.
//
/////////////////////////////////////////////////////////////////////////

#ifndef TSLIST_H_
#define TSLIST_H_

#include "TSApi.h"
#include "TSDef.h"
#include "TSObject.h"
#include "TSSocket.h"

#pragma warning( disable: 4710 )  // inlined function not inlined

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Position object for list iteration.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

class TS_API TSPosition
{

  public:

    TSPosition();
    TSPosition( TSPosition* nextPos, TSPosition* prevPos, TSObject* thisObj );
    TSPosition* next;
    TSPosition* prev;
    TSObject* object;

};

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Base class for all lists.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

class TS_API TSList
{

  public:

    TSList();
    TSList( const TSList& sourceList );
    ~TSList();

    TSList& operator=( const TSList& sourceList );

    TSPosition* GetFirst() const;
    TSPosition* GetNext( TSPosition* pos ) const;
    TSPosition* GetPrev( TSPosition* pos ) const;
    TSPosition* GetLast() const;
    TSPosition* Get( int index ) const;

    int InsertBefore( TSPosition* pos, TSObject* object );
    int InsertAfter( TSPosition* pos, TSObject* object );
    int AddHead( TSObject* object );
    int AddTail( TSObject* object );

    TSObject* GetAt( TSPosition* pos ) const;

    int Length() const { return length; }

    TSObject* RemoveObject( int index );
    TSObject* RemoveObject( TSPosition* pos );
    TSObject* RemoveObject( TSObject* pObject );

    int  Duplicate( TSList* newList, int type = 0 ) const;
    int  Copy( const TSList* sourceList );
    void EmptyList();
    void EmptyAndDestroyList();

    virtual int SocketString( TSString& out );
    TSString StringDump( int recursive, TSString indentation );

  private:

    TSPosition* first;
    TSPosition* last;
    int length;

};

class TSRecord;
class TSInteger;
class TSField;
class TSServer;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Derived list classes.  A derived class was needed so that these classes
 * can define their own way of receiving themselves off of the socket.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

class TS_API TSRecordList : public TSList
{

  public:

    TSRecordList();
    virtual ~TSRecordList();

    TSRecord* GetAt( TSPosition* pos )
              { return (TSRecord*)TSList::GetAt( pos ); }

    virtual TSRecord* FindRecord( int recId);
    virtual TSRecord* FindRecord( const char* fieldName, int searchValue );
    virtual TSRecord* FindRecord( const char* fieldName, double searchValue );
    virtual TSRecord* FindRecord( const char* fieldName, const char* searchValue );
    virtual TSRecord* FindRecord( const char* fieldName, int nTableId, int nFieldType, int nSqlDataType );
    virtual TSRecord* FindRecordByDbName( const char* fieldDbName, int nTableId, int nFieldType, int nSqlDataType );

    int Receive( TSServer* server, TSSocket* socket );
    virtual int SocketString( TSString& out );
    void SetIsFieldList( BOOL bIsFields ) { m_bIsFieldList = bIsFields; }

  private:

    BOOL m_bIsFieldList;

};

class TS_API TSFieldList : public TSList
{

  public:

    TSField* GetAt( TSPosition* pos )
              { return (TSField*)TSList::GetAt( pos ); }
    TSString DumpSchema( TSString indentation );
    TSField* FindFieldByName( const char* fieldName, int fieldType = 0 );

};

class TS_API TSTreeList : public TSRecordList
{
  public:

    virtual TSRecord* FindRecord( int recId );
    virtual TSRecord* FindRecord( const char* fieldName, int searchValue );
    virtual TSRecord* FindRecord( const char* fieldName, double searchValue );
    virtual TSRecord* FindRecord( const char* fieldName, const char* searchValue );

};

#endif

