/* -*- 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 "FB2ParserContext.h"
#include "FB2TextContext.h"
#include "FB2Token.h"

namespace libebook
{

FB2ParserContext::FB2ParserContext(FB2ParserContext *const parentContext, FB2Collector *const collector)
  : m_collector(collector ? collector : (parentContext ? parentContext->m_collector : 0))
  , m_parentContext(parentContext)
{
}

FB2XMLParserContext *FB2ParserContext::leaveContext() const
{
  FB2ParserContext *const parentContext = m_parentContext;
  delete this;
  return parentContext;
}

FB2Collector *FB2ParserContext::getCollector() const
{
  return m_collector;
}

FB2ParserContext *FB2ParserContext::getParentContext() const
{
  return m_parentContext;
}

FB2NodeContextBase::FB2NodeContextBase(FB2ParserContext *const parentContext, FB2Collector *const collector)
  : FB2ParserContext(parentContext, collector)
{
}

void FB2NodeContextBase::startOfElement()
{
}

void FB2NodeContextBase::endOfAttributes()
{
}

void FB2NodeContextBase::text(const char *)
{
}

FB2DataContextBase::FB2DataContextBase(FB2ParserContext *const parentContext)
  : FB2ParserContext(parentContext)
{
}

FB2XMLParserContext *FB2DataContextBase::element(const FB2TokenData &, const FB2TokenData &)
{
  return 0;
}

void FB2DataContextBase::startOfElement()
{
}

void FB2DataContextBase::endOfAttributes()
{
}

void FB2DataContextBase::text(const char *)
{
}

FB2TextContextBase::FB2TextContextBase(FB2ParserContext *const parentContext)
  : FB2ParserContext(parentContext)
{
}

FB2XMLParserContext *FB2TextContextBase::element(const FB2TokenData &, const FB2TokenData &)
{
  return 0;
}

void FB2TextContextBase::startOfElement()
{
}

void FB2TextContextBase::endOfElement()
{
}

void FB2TextContextBase::attribute(const FB2TokenData &, const FB2TokenData *, const char *)
{
}

void FB2TextContextBase::endOfAttributes()
{
}

FB2SkipElementContext::FB2SkipElementContext(FB2ParserContext *const parentContext)
  : FB2ParserContext(parentContext)
  , m_level(1)
{
}

FB2XMLParserContext *FB2SkipElementContext::leaveContext() const
{
  if (m_level)
    return const_cast<FB2SkipElementContext *>(this);

  FB2ParserContext *const parentContext = getParentContext();
  delete this;
  return parentContext;
}

FB2XMLParserContext *FB2SkipElementContext::element(const FB2TokenData &, const FB2TokenData &)
{
  ++m_level;
  return this;
}

void FB2SkipElementContext::startOfElement()
{
}

void FB2SkipElementContext::endOfElement()
{
  --m_level;
}

void FB2SkipElementContext::attribute(const FB2TokenData &, const FB2TokenData *, const char *)
{
}

void FB2SkipElementContext::endOfAttributes()
{
}

void FB2SkipElementContext::text(const char *)
{
}

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

FB2Style &FB2StyleContextBase::getStyle()
{
  return m_style;
}

FB2TextFormat &FB2StyleContextBase::getTextFormat()
{
  return m_style.getTextFormat();
}

FB2XMLParserContext *FB2StyleContextBase::element(const FB2TokenData &name, const FB2TokenData &ns)
{
  if (FB2Token::NS_FICTIONBOOK == getFB2TokenID(ns))
  {
    switch (getFB2TokenID(name))
    {
    case FB2Token::strong :
      return new FB2StrongContext(this, getStyle());
    case FB2Token::emphasis :
      return new FB2EmphasisContext(this, getStyle());
    case FB2Token::style :
      return new FB2StyleContext(this, getStyle());
    case FB2Token::a :
      return new FB2AContext(this, getStyle());
    case FB2Token::strikethrough :
      return new FB2StrikethroughContext(this, getStyle());
    case FB2Token::sub :
      return new FB2SubContext(this, getStyle());
    case FB2Token::sup :
      return new FB2SupContext(this, getStyle());
    case FB2Token::code :
      return new FB2CodeContext(this, getStyle());
    case FB2Token::image :
      return new FB2InlineImageContext(this, getStyle());
    default :
      break;
    }
  }

  return new FB2SkipElementContext(this);
}

void FB2StyleContextBase::endOfElement()
{
}

void FB2StyleContextBase::endOfAttributes()
{
}

void FB2StyleContextBase::attribute(const FB2TokenData &name, const FB2TokenData *ns, const char *const value)
{
  if ((FB2Token::NS_XML == getFB2TokenID(ns)) && (FB2Token::lang == getFB2TokenID(name)))
    m_style.getTextFormat().lang = value;
}

void FB2StyleContextBase::text(const char *value)
{
  getCollector()->openSpan(getStyle());
  getCollector()->insertText(value);
  getCollector()->closeSpan();
}

FB2BlockFormatContextBase::FB2BlockFormatContextBase(FB2ParserContext *parentContext, const FB2BlockFormat &format)
  : FB2NodeContextBase(parentContext)
  , m_format(format)
{
}

FB2BlockFormat &FB2BlockFormatContextBase::getBlockFormat()
{
  return m_format;
}

const FB2BlockFormat &FB2BlockFormatContextBase::getBlockFormat() const
{
  return m_format;
}

void FB2BlockFormatContextBase::setLang(const char *const lang)
{
  m_format.lang = lang;
}

}

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