/*
    SPDX-License-Identifier: GPL-2.0-or-later

    SPDX-FileCopyrightText: 2003 Brian Thomas <thomas@mail630.gsfc.nasa.gov>
    SPDX-FileCopyrightText: 2004-2022 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
*/

#include "codemethodblock.h"

#include "codeclassfield.h"
#include "classifiercodedocument.h"
#include "codegenerationpolicy.h"
#include "umlapp.h"

#include <QXmlStreamWriter>

CodeMethodBlock::CodeMethodBlock(ClassifierCodeDocument * doc, UMLObject * parentObj, const QString & body, const QString & comment)
  : OwnedCodeBlock (parentObj), CodeBlockWithComments ((CodeDocument*)doc, body, comment) 
{
    m_startMethod.clear();
    m_endMethod.clear();
}

CodeMethodBlock::~CodeMethodBlock()
{ 
}

/**
 * Get the parent code document.
 */
CodeDocument * CodeMethodBlock::getParentDocument()
{
    // we can just call the superclass
    return TextBlock::getParentDocument();
}

/**
 * Get the starting text that begins this method before the body is printed.
 */
QString CodeMethodBlock::getStartMethodText() const
{
    return m_startMethod;
}

/**
 * Get the ending text that finishes this method after the body is printed.
 */
QString CodeMethodBlock::getEndMethodText() const
{
    return m_endMethod;
}

/**
 * Set the starting text that begins this method before the body is printed.
 */
void CodeMethodBlock::setStartMethodText (const QString &value)
{
    m_startMethod = value;
}

/**
 * Set the ending text that finishes this method after the body is printed.
 */
void CodeMethodBlock::setEndMethodText(const QString &value)
{
    m_endMethod = value;
}

/**
 * Causes the text block to release all of its connections
 * and any other text blocks that it 'owns'.
 * needed to be called prior to deletion of the textblock.
 */
void CodeMethodBlock::release ()
{
    // just call super-class versions
    OwnedCodeBlock::release();
    TextBlock::release();
}

/**
 * Set attributes of the node that represents this class
 * in the XMI document.
 */
void CodeMethodBlock::setAttributesOnNode(QXmlStreamWriter& writer)
{
    // set super-class attributes
    CodeBlockWithComments::setAttributesOnNode(writer);
    OwnedCodeBlock::setAttributesOnNode(writer);

    // set local class attributes
    if (contentType() != AutoGenerated)
    {
        QString endLine = UMLApp::app()->commonPolicy()->getNewLineEndingChars();
        writer.writeAttribute(QStringLiteral("startMethodText"), encodeText(getStartMethodText(), endLine));
        writer.writeAttribute(QStringLiteral("endMethodText"), encodeText(getEndMethodText(), endLine));
    }
}

/**
 * Set the class attributes of this object from
 * the passed element node.
 */
void CodeMethodBlock::setAttributesFromNode(QDomElement & elem)
{
    // set attributes from the XMI
    CodeBlockWithComments::setAttributesFromNode(elem); // superclass load
    OwnedCodeBlock::setAttributesFromNode(elem); // superclass load

    // now load local attributes
    if (contentType() != AutoGenerated)
    {
        QString endLine = UMLApp::app()->commonPolicy()->getNewLineEndingChars();
        setStartMethodText(decodeText(elem.attribute(QStringLiteral("startMethodText")), endLine));
        setEndMethodText(decodeText(elem.attribute(QStringLiteral("endMethodText")), endLine));
    }
}

/**
 * Set the class attributes from a passed object
 */
void CodeMethodBlock::setAttributesFromObject(TextBlock * obj)
{
    CodeBlockWithComments::setAttributesFromObject(obj);

    CodeMethodBlock * mb = dynamic_cast<CodeMethodBlock*>(obj);
    if (mb)
    {
        setStartMethodText(mb->getStartMethodText());
        setEndMethodText(mb->getEndMethodText());
    }
}

/**
 * @return  QString
 */
QString CodeMethodBlock::toString() const
{
    QString string;

    if (getWriteOutText()) {
        QString indent = getIndentationString();
        QString bodyIndent = getIndentationString(getIndentationLevel()+1);
        QString endLine = UMLApp::app()->commonPolicy()->getNewLineEndingChars();

        QString startMethod = formatMultiLineText (getStartMethodText(), indent, endLine);
        QString body = formatMultiLineText (getText(), bodyIndent, endLine);
        QString endMethod = formatMultiLineText(getEndMethodText(), indent, endLine);

        QString comment = getComment()->toString();
        if (!comment.isEmpty() && getComment()->getWriteOutText())
            string.append(comment);

        if (!startMethod.isEmpty())
            string.append(startMethod);

        if (!body.isEmpty())
            string.append(body);

        if (!endMethod.isEmpty())
            string.append(endMethod);

    }
    return string;
}

void CodeMethodBlock::syncToParent()
{
    getComment()->setText(getParentObject()->doc());

    updateMethodDeclaration();

    // only update IF we are NOT AutoGenerated
    if (contentType() != AutoGenerated)
        return;

    updateContent();
}

