/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libe-book 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 "FB2Collector.h"
#include "FB2TextContext.h"
#include "FB2Token.h"

namespace libebook
{

FB2ParaContextBase::FB2ParaContextBase(FB2ParserContext *parentContext, const FB2BlockFormat &format)
  : FB2StyleContextBase(parentContext, FB2Style(format))
{
}

void FB2ParaContextBase::startOfElement()
{
  getCollector()->openParagraph(getStyle().getBlockFormat());
}

void FB2ParaContextBase::endOfElement()
{
  getCollector()->closeParagraph();
}

void FB2ParaContextBase::attribute(const FB2TokenData &name, const FB2TokenData *ns, const char *value)
{
  FB2StyleContextBase::attribute(name, ns, value);

  if (FB2_NO_NAMESPACE(ns))
  {
    switch (getFB2TokenID(name))
    {
    case FB2Token::id :
      getCollector()->defineID(value);
      break;
    case FB2Token::style :
      // ignore
      break;
    default :
      break;
    }
  }
}

FB2AContext::FB2AContext(FB2ParserContext *parentContext, const FB2Style &style)
  : FB2StyleContextBase(parentContext, style)
  , m_href()
  , m_valid(true)
  , m_note(false)
{
}

void FB2AContext::startOfElement()
{
}

void FB2AContext::endOfAttributes()
{
  if (!m_valid)
    m_note = false;

  if (m_note)
  {
    if ('#' == m_href[0])
      m_href = m_href.substr(1);
    else
      m_note = false;
  }
}

void FB2AContext::attribute(const FB2TokenData &name, const FB2TokenData *ns, const char *value)
{
  if (FB2Token::NS_XLINK == getFB2TokenID(ns))
  {
    switch (getFB2TokenID(name))
    {
    case FB2Token::href :
      m_href = value;
      break;
    case FB2Token::type :
      m_valid = FB2Token::simple == getFB2TokenID(value);
      break;
    default :
      break;
    }
  }
  else if (FB2_NO_NAMESPACE(ns) && (FB2Token::type == getFB2TokenID(name)))
    m_note = FB2Token::note == getFB2TokenID(value);
}

void FB2AContext::text(const char *value)
{
  if (m_note)
    getCollector()->insertFootnote(m_href.c_str());
  else
  {
    // just put the text in
    getCollector()->openSpan(getStyle());
    getCollector()->insertText(value);
    getCollector()->closeSpan();
  }
}

FB2CodeContext::FB2CodeContext(FB2ParserContext *parentContext, FB2Style &style)
  : FB2StyleContextBase(parentContext, style)
{
}

void FB2CodeContext::startOfElement()
{
  getTextFormat().code = true;
}

FB2EmphasisContext::FB2EmphasisContext(FB2ParserContext *parentContext, FB2Style &style)
  : FB2StyleContextBase(parentContext, style)
{
}

void FB2EmphasisContext::startOfElement()
{
  getTextFormat().emphasis = true;
}

FB2InlineImageContext::FB2InlineImageContext(FB2ParserContext *parentContext, const FB2Style &style)
  : FB2DataContextBase(parentContext)
  , m_style(style)
  , m_href()
  , m_altText()
  , m_valid(true)
{
}

void FB2InlineImageContext::startOfElement()
{
}

void FB2InlineImageContext::endOfElement()
{
  if (m_valid && ('#' != m_href[0]))
    m_valid = false;

  if (m_valid)
    getCollector()->insertBitmap(m_href.substr(1).c_str());
  else
  {
    getCollector()->openSpan(m_style);
    const std::string altText("[Image: " + m_altText + "]");
    getCollector()->insertText(altText.c_str());
    getCollector()->closeSpan();
  }
}

void FB2InlineImageContext::endOfAttributes()
{
}

void FB2InlineImageContext::attribute(const FB2TokenData &name, const FB2TokenData *ns, const char *value)
{
  if (FB2_NO_NAMESPACE(ns) && (FB2Token::alt == getFB2TokenID(name)))
    m_altText = value;
  else if (FB2Token::NS_XLINK == getFB2TokenID(ns))
  {
    switch (getFB2TokenID(name))
    {
    case FB2Token::href :
      m_href = value;
      break;
    case FB2Token::type :
      m_valid = FB2Token::simple == getFB2TokenID(value);
      break;
    default :
      break;
    }
  }
}

FB2PContext::FB2PContext(FB2ParserContext *const parentContext, const FB2BlockFormat &format)
  : FB2ParaContextBase(parentContext, makeBlockFormat(format))
{
}

FB2BlockFormat FB2PContext::makeBlockFormat(const FB2BlockFormat &format)
{
  FB2BlockFormat outFormat(format);
  outFormat.p = true;
  return outFormat;
}

FB2StrikethroughContext::FB2StrikethroughContext(FB2ParserContext *parentContext, FB2Style &style)
  : FB2StyleContextBase(parentContext, style)
{
}

void FB2StrikethroughContext::startOfElement()
{
  getTextFormat().strikethrough = true;
}

FB2StrongContext::FB2StrongContext(FB2ParserContext *parentContext, FB2Style &style)
  : FB2StyleContextBase(parentContext, style)
{
}

void FB2StrongContext::startOfElement()
{
  getTextFormat().strong = true;
}

FB2StyleContext::FB2StyleContext(FB2ParserContext *parentContext, FB2Style &style)
  : FB2StyleContextBase(parentContext, style)
{
}

void FB2StyleContext::startOfElement()
{
  // TODO: implement me
}

FB2SubContext::FB2SubContext(FB2ParserContext *parentContext, FB2Style &style)
  : FB2StyleContextBase(parentContext, style)
{
}

void FB2SubContext::startOfElement()
{
  getTextFormat().sub = true;
}

FB2SubtitleContext::FB2SubtitleContext(FB2ParserContext *parentContext, const FB2BlockFormat &format)
  : FB2ParaContextBase(parentContext, makeBlockFormat(format))
{
}

FB2BlockFormat FB2SubtitleContext::makeBlockFormat(const FB2BlockFormat &format)
{
  FB2BlockFormat outFormat(format);
  outFormat.subtitle = true;
  return outFormat;
}

FB2SupContext::FB2SupContext(FB2ParserContext *parentContext, FB2Style &style)
  : FB2StyleContextBase(parentContext, style)
{
}

void FB2SupContext::startOfElement()
{
  getTextFormat().sup = true;
}

FB2TextAuthorContext::FB2TextAuthorContext(FB2ParserContext *parentContext, const FB2BlockFormat &format)
  : FB2PContext(parentContext, makeBlockFormat(format))
{
}

FB2BlockFormat FB2TextAuthorContext::makeBlockFormat(const FB2BlockFormat &format)
{
  FB2BlockFormat outFormat(format);
  outFormat.textAuthor = true;
  return outFormat;
}

FB2VContext::FB2VContext(FB2ParserContext *parentContext, const FB2BlockFormat &format)
  : FB2ParaContextBase(parentContext, makeBlockFormat(format))
{
}

FB2BlockFormat FB2VContext::makeBlockFormat(const FB2BlockFormat &format)
{
  FB2BlockFormat outFormat(format);
  outFormat.v = true;
  return outFormat;
}

}

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