#ifndef DOC_TEMPLATE_H
#define DOC_TEMPLATE_H


#include <vector>
#include <string>
#include "DocOutput.h"
#include "Utilities.h"


enum DocItemType
{
  DIT_Defaults,
  DIT_Page,
  DIT_Background,
  DIT_Label,
  DIT_Image,
  DIT_Line,
  DIT_Box,
  DIT_Circle,
  DIT_Ellipse,
  DIT_Polygon,
  DIT_Spline,
  DIT_Shape,
  DIT_Unknown,
  DIT_Last = DIT_Unknown
};

std::string stringFromDocItemType(DocItemType typ);
DocItemType stringToDocItemType(const std::string& str);


enum TemplateRole
{
  TR_CoverPage,
  TR_Document,
  TR_Both,
  TR_Last = TR_Both
};

std::string stringFromTemplateRole(TemplateRole rol);
TemplateRole stringToTemplateRole(const std::string& str);


enum PenStyle
{
  PS_Solid,
  PS_Dashed,
  PS_Last = PS_Dashed
};


enum Align
{
  AL_Left     = 0x01,
  AL_HCenter  = 0x02,
  AL_Right    = 0x04,

  AL_Top      = 0x08,
  AL_VCenter  = 0x10,
  AL_Bottom   = 0x20
};


std::string stringFromAlignment(Align align);
Align stringToAlignment(const std::string& str);


struct Point
{
  float x, y;
};


std::string stringFromPoint(const Point& pnt);
Point stringToPoint(const std::string& str);


std::string stringFromPolygon(const std::vector<Point>& poly);
std::vector<Point> stringToPolygon(const std::string& str);


struct DocTemplateItem
{
  DocItemType        m_type;
  TemplateRole       m_role;
  float              m_alpha;
  unsigned int       m_bgColor; // flat color only at the moment
  Point              m_pos;
  Point              m_size;
  std::string        m_font;
  float              m_fontSize;
  unsigned int       m_fontColor;
  unsigned int       m_fillColor;
  unsigned int       m_penColor;
  float              m_penWidth;
  PenStyle           m_penStyle;
  Align              m_alignment;
  Align              m_boundsAlignment;

  // really just need a union of these 3 below, but can't do that easily so just use up a bit of extra space here
  std::string        m_text;
  std::vector<Point> m_shape;
  std::string        m_imageFile;
};


class DocTemplate
{
public:
  DocTemplate();
  ~DocTemplate();

  void ReadTemplateFile(const char* a_fileName);
  void Apply(DocOutputPage& page);
  void Save();

  const std::vector<DocTemplateItem>& Items() const  { return m_items; }

  void PageBounds(Point& topLeft, Point& bottomRight) const
  {
    topLeft = m_pageTopLeft;
    bottomRight = m_pageBottomRight;
  }

  void SetPageBounds(const Point& topLeft, const Point& bottomRight)
  {
    m_pageTopLeft = topLeft;
    m_pageBottomRight = bottomRight;
  }

  void Columns(int& columns, float& columnSpacing) const
  {
    columns = m_columns;
    columnSpacing = m_columnSpacing;
  }

  void SetColumns(int columns, float columnSpacing)
  {
    m_columns = columns;
    m_columnSpacing = columnSpacing;
  }

  void UpdateItem(int idx, const DocTemplateItem& item)
  {
    if (idx >= 0 && m_items.size() > idx)
      m_items[idx] = item;
  }

  void DeleteItem(int idx)
  {
    if (idx >= 0 && idx < m_items.size())
      m_items.erase(m_items.begin() + idx);
  }

  void AddItem(DocItemType a_type)
  {
    DocTemplateItem newItem;
    newItem = m_defaults;
    newItem.m_type = a_type;
    m_items.push_back(newItem);
  }

  int MoveItemUp(int idx)
  {
    if (idx < 0 || idx >= m_items.size())
      return -1;
    if (idx == 0)
      return 0;
    if (idx == 1)
      return 1;
    DocTemplateItem tmp = m_items[idx - 1];
    m_items[idx - 1] = m_items[idx];
    m_items[idx] = tmp;
    return idx - 1;
  }

  int MoveItemDown(int idx)
  {
    if (idx < 0 || idx >= m_items.size())
      return -1;
    if (idx == 0)
      return 0;
    if (idx == (m_items.size() - 1))
      return idx;
    DocTemplateItem tmp = m_items[idx + 1];
    m_items[idx + 1] = m_items[idx];
    m_items[idx] = tmp;
    return idx + 1;
  }

  static void LogMessage(yqLogLevel a_level, const char* a_msg, ...);

private:
  void WriteTemplateFile(const char* a_fileName);

  DocTemplateItem              m_defaultDefaults;
  DocTemplateItem              m_defaults;
  std::vector<DocTemplateItem> m_items;
  Point                        m_pageTopLeft;
  Point                        m_pageBottomRight;
  int                          m_columns;
  float                        m_columnSpacing;
  static std::string           m_currentFile;
  static unsigned int          m_currentLine;
};


#endif // DOC_TEMPLATE_H

