/***************************************************************************
 *   Copyright (C) 2004 by Hans Oischinger                                 *
 *   hans.oischinger@kdemail.net                                           *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.             *
 ***************************************************************************/
#include "urireference.h"

// Elements
#include "elements/elementnode.h"
#include "elements/documentelement.h"

// Visitors
#include "visitors/avisitor.h"

// KDE
#include <kdebug.h>

URIReference::URIReference( ElementNode* parent, bool referenceParentIfInvalid )
    : Attribute( ATTR_REF ),
    m_parentElement(parent),
    m_URI(0),
    m_ref(0),
    m_referenceParentIfInvalid(referenceParentIfInvalid)
{
  // if (!parent)
  //   kdWarning() << "URIReference::URIReference() - NULL parent given. This won't work" << endl;
}

URIReference::~URIReference()
{}

/**
 * Overloaded = Operator
 * Note that the m_parentElement Attr won't be copied
 */
URIReference& URIReference::operator=(const URIReference &other)
{
  Attribute::operator=(other);
  m_referenceParentIfInvalid = other.getReferenceParentIfInvalid();
  m_URI = other.getURI();
  m_ref = other.m_ref;
  return *this;
}

Attribute* URIReference::clone()
{
  URIReference* retElem = new URIReference(m_parentElement, m_referenceParentIfInvalid);
  *retElem = *this;
  return ( retElem );
}

ElementNode* URIReference::getRefElement()
{
  if (m_ref)
  {
    Q_CHECK_PTR( m_ref );

    // Check for local links
    QString normalizedRef = m_URI;
    if (normalizedRef.left(1)=="#") // is this a local reference
      normalizedRef = normalizedRef.remove(0,1);
    else
    {
      kdWarning() << "URIReference::getRefElement() - Non-local references not handled yet" << endl;
      return 0;
    }

    if ( normalizedRef == m_ref->id() )
      return m_ref;
    else
    {
      kdWarning() << "URIReference::getRefElement() - URI " << m_URI << " and referenced element are not consistant" << endl;
      ElementNode* newRef = 0;
      newRef = searchRefElementforURI();
      if (newRef)
      {
        if ( newRef->getState() == Element::deleted )
        {
          kdWarning() << "URIReference::getRefElement() - PaintServer is no more valid / has been deleted" << m_URI << endl;
          return 0;
        }
        setRefElement( newRef );
        return  m_ref;
      }
      else
      {
        kdWarning() << "URIReference::getRefElement() - No reference found for URI " << m_URI << endl;
        return 0;
      }
    }
  }
  else
  {
    if (m_referenceParentIfInvalid && m_parentElement)
      return m_parentElement->getParent();
  }
  return 0;
}

ElementNode* URIReference::searchRefElementforURI() const
{
  if (!m_parentElement)
  {
    kdWarning() << "URIReference::searchRefElementforURI() - no parentElement given. Search won't work" << endl;
    return 0;
  }

  // Search for parent element
  ElementNode* rootElem = m_parentElement->getParent();
  while ( rootElem->getParent() )
    rootElem = rootElem->getParent();
  if (!rootElem)
    rootElem = m_parentElement;

  // Check if rootElem is a DocumentElement
  if ( rootElem->inherits("DocumentElement") )
  {
    return static_cast<DocumentElement*>(rootElem)->findElementByRef( m_URI );
  }
  else
  {
    // This should not happen ( we do not have a DocumentElem as Root )
    kdWarning() << "URIReference::searchRefElementforURI() - Root node is not a DocumentElement!!!" << endl;
  }
  return 0;
}

/**
 * Returns the local reference without the trailing # if exists
 * @return 
 */
QString URIReference::getLocalURI() const
{
  // Check for local links
  QString normalizedRef = m_URI;
  if (normalizedRef.left(1)=="#") // is this a local reference
    return normalizedRef.remove(0,1);
  else
    return QString::null;
}

void URIReference::accept( AVisitor &a )
{
  a.visit(*this);
}

void URIReference::setRefElement( ElementNode * ref )
{
  m_ref = ref;
   if (m_ref)
     m_URI = "#" + m_ref->id();
}
