// ---------------------------------------------------------------------------
// - Sheet.hpp                                                               -
// - afnix:sps library - sheet class definition                              -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - This program  is  distributed in  the hope  that it will be useful, but -
// - without  any  warranty;  without  even   the   implied    warranty   of -
// - merchantability or fitness for a particular purpose.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2005 amaury darsch                                   -
// ---------------------------------------------------------------------------

#ifndef  AFNIX_SHEET_HPP
#define  AFNIX_SHEET_HPP

#ifndef  AFNIX_RECORD_HPP
#include "Record.hpp"
#endif

#ifndef  AFNIX_PRINTTABLEHPP
#include "PrintTable.hpp"
#endif

namespace afnix {

  /// The Sheet class is a collection of records. Because of the record
  /// format, a sheet look like a 2-dimensional array of cells. Like the
  /// record, the sheet is defined with a name and a vector of records.
  /// For format purpose, the sheet has also three record fields, namelly,
  /// the info, head, and foot record.
  /// @author amaury darsch

  class Sheet : public Persist {
  private:
    /// the sheet name
    long   d_quark;
    /// the record info
    Record  d_info;
    /// the record header
    Record  d_head;
    /// the record footer
    Record  d_foot;
    /// the record vector
    Vector  d_vrcds;
    
  public:
    /// create an empty sheet
    Sheet (void);

    /// create a new sheet with a name
    /// @param name the sheet name
    Sheet (const String& name);

    /// @return the object name
    String repr (void) const;

    /// @return the format serial id
    t_byte serialid (void) const;

    /// serialize this sheet
    /// @param os the output stream
    void wrstream (Output& os) const;

    /// deserialize this sheet
    /// @param is the input stream
    void rdstream (Input& os);

    /// @return the sheet name
    String getname (void) const;

    /// set the sheet name
    /// @param name the name to set
    void setname (const String& name);

    /// add a new information object (cell or literal)
    /// @param object the object to add
    void addinfo (Object* object);

    /// add a vector of object in the info descriptor
    /// @param argv the object vector
    void addinfo (const Vector* argv);

    /// @return an info cell by index
    Cell* getinfo (const long index) const;

    /// @return a literal information by index
    Literal* mapinfo (const long index) const;

    /// set the information record by index and literal
    /// @param index the info index to set
    /// @param lobj  the literal object to set
    void setinfo (const long index, Literal* lobj);

    /// add a new object in the header (cell or literal)
    /// @param object the object to add
    void addhead (Object* object);

    /// add a vector of object in the header descriptor
    /// @param argv the object vector
    void addhead (const Vector* argv);

    /// @return a header cell by index
    Cell* gethead (const long index) const;

    /// @return a header literal by index
    Literal* maphead (const long index) const;

    /// set the record header by index and literal
    /// @param index the info index to set
    /// @param lobj  the literal object to set
    void sethead (const long index, Literal* lobj);

    /// add a new object in the footer (cell or literal)
    /// @param object the object to add
    void addfoot (Object* object);

    /// add a vector of object in the footer descriptor
    /// @param argv the object vector
    void addfoot (const Vector* argv);

    /// @return a footer cell by index
    Cell* getfoot (const long index) const;

    /// @return a footer cell value by index
    Literal* mapfoot (const long index) const;

    /// set the record footer by index and literal
    /// @param index the info index to set
    /// @param lobj  the literal object to set
    void setfoot (const long index, Literal* lobj);

    /// add a new record in this sheet
    /// @param rcd the record to add
    void add (Record* rcd);

    /// @return a record by index
    Record* get (const long index) const;

    /// set a record in this sheet by index
    /// @param index the record index
    /// @param rcd   the record to set
    void set (const long index, Record* rcd);

    /// add a vector of objects in this sheet
    /// @param argv the vector to add
    void adddata (const Vector* argv);

    /// @return the sheet length
    long length (void) const;

    /// @return the number of columns
    long getcols (void) const;

    /// import data in the sheet
    /// @param is the input stream
    void import (Input* is);

    /// convert a sheet into a print sheet
    /// @param max the maximum number of rows
    /// @param start the row start index
    /// @param flag  the use string or literal represenntation
    PrintTable* convert (long max, long start, bool flag) const;

    /// sort this record by ascending or descending order and column
    /// @param col  the column used for sorting
    /// @param mode the ascending mode
    void sort (const long col, const bool mode);

    /// generate a new sheet
    /// @param argv the argument vector
    static Object* mknew (Vector* argv);

    /// apply this sheet with a set of arguments and a quark
    /// @param robj  robj the current runnable
    /// @param nset  the current nameset    
    /// @param quark the quark to apply these arguments
    /// @param argv  the arguments to apply
    Object* apply (Runnable* robj, Nameset* nset, const long quark,
                   Vector* argv);
    
  private:
    // make the copy constructor private
    Sheet (const Sheet&);
    // make the assignment operator private
    Sheet& operator = (const Sheet&);
  };
}

#endif
