/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libepubgen project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sstream>

#include <librevenge/librevenge.h>

#include "libepubgen_utils.h"
#include "EPUBCSSSink.h"
#include "EPUBTableStyleManager.h"

namespace libepubgen
{

using librevenge::RVNGPropertyList;
using librevenge::RVNGPropertyListVector;
using librevenge::RVNGString;

void EPUBTableStyleManager::openTable(RVNGPropertyListVector const &colList)
{
  std::vector<double> colWidths;
  for (unsigned long i = 0; i < colList.count(); i++)
  {
    RVNGPropertyList const &prop=colList[i];
    double width=0;
    if (prop["style:column-width"])
    {
      librevenge::RVNGUnit unit=prop["style:column-width"]->getUnit();
      if (unit==librevenge::RVNG_POINT)
        width=prop["style:column-width"]->getDouble()/72.;
      else if (unit==librevenge::RVNG_INCH)
        width=prop["style:column-width"]->getDouble();
      else if (unit==librevenge::RVNG_TWIP)
        width=prop["style:column-width"]->getDouble()/1440.;
    }
    colWidths.push_back(width);
  }
  m_columWitdhsStack.push_back(colWidths);
}

void EPUBTableStyleManager::closeTable()
{
  if (!m_columWitdhsStack.size())
  {
    EPUBGEN_DEBUG_MSG(("EPUBTableStyleManager::closeTable: can not find the columns witdh\n"));
    return;
  }
  m_columWitdhsStack.pop_back();
}

bool EPUBTableStyleManager::getColumnsWidth(int col, int numSpanned, double &w) const
{
  if (!m_columWitdhsStack.size())
    return false;
  std::vector<double> const &widths=m_columWitdhsStack.back();
  if (col < 0 || size_t(col+numSpanned-1) >= widths.size())
  {
    EPUBGEN_DEBUG_MSG(("EPUBTableStyleManager::getColumnsWidth: can not compute the columns witdh\n"));
    return false;
  }
  bool fixed = true;
  w = 0;
  for (size_t i=size_t(col); i < size_t(col+numSpanned); i++)
  {
    if (widths[i] < 0)
    {
      w += -widths[i];
      fixed = false;
    }
    else if (widths[i] > 0)
      w += widths[i];
    else
    {
      w = 0;
      return true;
    }
  }
  if (!fixed) w = -w;
  return true;
}

std::string EPUBTableStyleManager::getCellClass(RVNGPropertyList const &pList)
{
  EPUBCSSProperties content;
  extractCellProperties(pList, content);
  ContentNameMap_t::const_iterator it=m_cellContentNameMap.find(content);
  if (it != m_cellContentNameMap.end())
    return it->second;
  std::stringstream s;
  s << "cellTable" << m_cellContentNameMap.size();
  m_cellContentNameMap[content]=s.str();
  return s.str();
}

std::string EPUBTableStyleManager::getRowClass(RVNGPropertyList const &pList)
{
  EPUBCSSProperties content;
  extractRowProperties(pList, content);
  ContentNameMap_t::const_iterator it=m_rowContentNameMap.find(content);
  if (it != m_rowContentNameMap.end())
    return it->second;
  std::stringstream s;
  s << "rowTable" << m_rowContentNameMap.size();
  m_rowContentNameMap[content]=s.str();
  return s.str();
}

void EPUBTableStyleManager::send(EPUBCSSSink &out)
{
  for (ContentNameMap_t::const_iterator it=m_cellContentNameMap.begin(); m_cellContentNameMap.end() != it; ++it)
  {
    RVNGPropertyList props;
    fillPropertyList(it->first, props);
    out.insertRule(("." + it->second).c_str(), props);
  }

  for (ContentNameMap_t::const_iterator it=m_rowContentNameMap.begin(); m_rowContentNameMap.end() != it; ++it)
  {
    RVNGPropertyList props;
    fillPropertyList(it->first, props);
    out.insertRule(("." + it->second).c_str(), props);
  }
}

void EPUBTableStyleManager::extractCellProperties(RVNGPropertyList const &pList, EPUBCSSProperties &cssProps) const
{
  // try to get the cell width
  if (pList["librevenge:column"])
  {
    int c=pList["librevenge:column"]->getInt();
    int span=1;
    if (pList["table:number-columns-spanned"])
      span = pList["table:number-columns-spanned"]->getInt();
    double w;
    if (!getColumnsWidth(c,span,w))
    {
      EPUBGEN_DEBUG_MSG(("EPUBTableStyleManager::getCellContent: can not find columns witdth for %d[%d]\n", c, span));
    }
    else if (w > 0)
    {
      std::ostringstream width;
      width << w << "in";
      cssProps["width"] = width.str();
    }
    else if (w < 0)
    {
      std::ostringstream width;
      width << -w << "in";
      cssProps["min-width"] = width.str();
    }
  }
  if (pList["fo:text-align"])
  {
    if (pList["fo:text-align"]->getStr() == RVNGString("end")) // stupid OOo convention..
      cssProps["text-align"] = "right";
    else
      cssProps["text-align"] = pList["fo:text-align"]->getStr().cstr();
  }
  if (pList["style:vertical-align"])
    cssProps["vertical-align"] = pList["style:vertical-align"]->getStr().cstr();
  else
    cssProps["vertical-align"] = "top";
  if (pList["fo:background-color"])
    cssProps["background-color"] = pList["fo:background-color"]->getStr().cstr();

  static char const *(type[]) = {"border", "border-left", "border-top", "border-right", "border-bottom" };
  for (int i = 0; i < 5; i++)
  {
    std::string field("fo:");
    field+=type[i];
    if (!pList[field.c_str()])
      continue;
    cssProps[type[i]] = pList[field.c_str()]->getStr().cstr();
  }
}

void EPUBTableStyleManager::extractRowProperties(RVNGPropertyList const &pList, EPUBCSSProperties &cssProps) const
{
  if (pList["style:min-row-height"])
    cssProps["min-height"] = pList["style:min-row-height"]->getStr().cstr();
  else if (pList["style:row-height"])
    cssProps["height"] = pList["style:row-height"]->getStr().cstr();
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
