/*
_______________________________________________________________________________

                              TableGenerator v1.3

-------------------------------------------------------------------------------
Copyright (c) 2007-2010 Kai Braaten

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-------------------------------------------------------------------------------
*/

#ifndef _TABLESTRATEGY_HPP_
#define _TABLESTRATEGY_HPP_

#include <string>
#include <vector>
#include <sys/types.h>

namespace TableGen
{

class TableRow;

class TableStrategy
{
public:
  virtual ~TableStrategy() { };

  virtual std::string render( const std::vector< TableRow >&,
                              const std::vector< size_t >& ) = 0;

protected:
  TableStrategy() { };

private:
  // Disallow copying and assigning
  TableStrategy( const TableStrategy& );
  TableStrategy &operator=( const TableStrategy& );
};

class SimpleTable : public TableStrategy
{
public:
  SimpleTable( const int fieldspace = 1,    // Padding between fields
               const int columns = 1,       // Number of tables horizontally
               const int columnspace = 1,   // Space between tables
	       const std::string &nl = "\r\n" ); // newline marker
  virtual std::string render( const std::vector< TableRow >&,
                              const std::vector< size_t >& );

private:
  int _fieldspace;
  int _columns;
  int _columnspace;
  std::string _newline;
};

// Notes:
// First row is used for headers.
// Numeric fields are justified to the right, others to the left
class FramedTable : public TableStrategy
{
public:
  FramedTable( int columns = 1, // Number of TABLES stacked horizontally
               int space = 0, // Add extra padding
               const std::string &vcol = "",  // Field data colour token
               const std::string &fcol = "",  // Frame colour token
               const std::string &hcol = "",  // Header colour token
	       const std::string &fg = "+-|", // Frame graphics characters
	       const std::string &nl = "\r\n" ); // Newline marker
  virtual std::string render( const std::vector< TableRow >&,
                              const std::vector< size_t >& );

private:
  int _columns;
  int _space;
  std::string _vColour; // values
  std::string _fColour; // frames
  std::string _hColour; // headers
  std::string _frameGfx;
  std::string _newline;
};

class Space3Table : public TableStrategy
{
public:
  Space3Table( const std::string &h = "",      // Header text
	       const std::string &hcol = "",   // Header colour
	       const std::string &vcol = "",   // Field data colour
	       const std::string &nl = "\r\n" );
  virtual std::string render( const std::vector< TableRow >&,
			      const std::vector< size_t >& );

private:
  std::string _head;
  std::string _hColour;
  std::string _vColour;
  std::string _newline;
};

class ShadowTable : public TableStrategy
{
public:
  ShadowTable( const std::string &ht,        // Header text
	       const std::string &tc,        // Text colour
	       const std::string &fc,        // Background fill colour
	       const std::string &sc,        // Shadow colour
	       const std::string &st,        // Stop colour
	       size_t p = 0,                 // Inner padding
	       size_t fp = 1,                // Field padding
	       size_t ind = 0,               // Left border indentation
	       const std::string &cc = "",   // Closing colour tag
	       const std::string &nl = "\r\n" ); // newline character(s)
  virtual std::string render( const std::vector< TableRow >&,
                              const std::vector< size_t >& );

private:
  ShadowTable(); // Makes no sense to allow default constructor here.
  const std::string &addColour( const std::string& );
  std::string balanceColourTags();

  std::string _header;
  std::string _textColour;
  std::string _fillColour;
  std::string _shadowColour;
  std::string _stopColour;
  std::string _closeColour;
  std::string _newline;
  size_t _padding;
  size_t _columnPadding;
  size_t _indentation;
  unsigned long _depth;
};

class HtmlTable : public TableStrategy
{
public:
  HtmlTable( bool useHeader = true, // Make first row header
	     unsigned long borderWidth = 0, // Width of table border
	     // Title of HTML page
	     const std::string &pageTitle = "TableGenerator 1.3" );

  std::string render( const std::vector< TableRow >&,
		      const std::vector< size_t >& );

private:
  bool _useHeader;
  unsigned long _borderWidth;
  std::string _pageTitle;
};

}

#endif //include guard