/*
  This file is part of the KTextTemplate library

  SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>

  SPDX-License-Identifier: LGPL-2.1-or-later

*/

#include <iostream>

class QString
{
public:
    void operation1()
    {
        std::cout << "QString operation 1" << std::endl;
    }
    void operation2()
    {
        std::cout << "QString operation 2" << std::endl;
    }
};

class QVariant
{
public:
    QVariant()
    {
    }
    QVariant(const QString &)
    {
        std::cout << "QVariant::QVariant(QString)" << std::endl;
    }
};

class SafeString : public QString
{
public:
    operator QVariant() const
    {
        std::cout << "SafeString::operator QVariant()" << std::endl;
        return QVariant();
    }
};

class WrappingSafeString
{
public:
    WrappingSafeString()
    {
    }

    WrappingSafeString(const QString &)
    {
        std::cout << "WrappingSafeString::WrappingSafeString(QString)" << std::endl;
    }

    operator QVariant() const
    {
        std::cout << "WrappingSafeString::operator QVariant()" << std::endl;
        return QVariant();
    }

    operator QString() const
    {
        std::cout << "WrappingSafeString::operator QString()" << std::endl;
        return QString();
    }
};

class WrappingSubclassSafeString
{
public:
    WrappingSubclassSafeString()
        : m_wrappedSubclass(this)
        , m_isSafe(false)
    {
    }

    WrappingSubclassSafeString(const QString &)
        : m_wrappedSubclass(this)
        , m_isSafe(false)
    {
        std::cout << "WrappingSubclassSafeString::WrappingSubclassSafeString(QString)" << std::endl;
    }

    bool isSafe() const
    {
        return m_isSafe;
    };
    void setSafe(bool safe)
    {
        m_isSafe = safe;
    }

    class Subclass : public QString
    {
        friend class WrappingSubclassSafeString;
        Subclass(WrappingSubclassSafeString *wsss)
            : m_wsss(wsss)
        {
        }
        WrappingSubclassSafeString *m_wsss;

    public:
        void operation2()
        {
            m_wsss->m_isSafe = false;
            std::cout << "overridden string operation 2 (wrapping)" << std::endl;
        }
    };

    Subclass m_wrappedSubclass;

    Subclass *operator->()
    {
        return &m_wrappedSubclass;
    }

    operator QVariant() const
    {
        std::cout << "WrappingSubclassSafeString::operator QVariant()" << std::endl;
        return QVariant();
    }

    operator QString() const
    {
        std::cout << "WrappingSubclassSafeString::operator QString()" << std::endl;
        return m_wrappedSubclass;
    }

private:
    bool m_isSafe;
};

class UsingSafeString : private QString
{
public:
    UsingSafeString()
    {
    }
    UsingSafeString(const QString &)
    {
    }

    void operation2()
    {
        std::cout << "overridden string operation 2 (using)" << std::endl;
    };

    using QString::operation1;

    operator QVariant()
    {
        return QVariant();
    }

    operator QString()
    {
        return QString();
    }
};

QVariant f1()
{
    return QString();
}

QVariant f2()
{
    return SafeString();
}

QVariant f3()
{
    return WrappingSafeString();
}

QString f4()
{
    return WrappingSafeString();
}

WrappingSafeString f5()
{
    return QString();
}

QVariant f6()
{
    return WrappingSubclassSafeString();
}

QString f7()
{
    return WrappingSubclassSafeString();
}

WrappingSubclassSafeString f8()
{
    return QString();
}

#ifdef BROKEN

QVariant f9()
{
    return UsingSafeString();
}

QString f10()
{
    return UsingSafeString();
}

UsingSafeString f11()
{
    return QString();
}

#endif

int main(int argc, char **argv)
{
    f1();
    f2();
    f3();
    f4();
    f5();
    f6();
    f7();
    f8();
#ifdef BROKEN
    f9();
    f10();
    f11();
#endif

    WrappingSubclassSafeString wsss;
    wsss.setSafe(true);
    wsss->operation1();
    std::cout << (wsss.isSafe() ? "IsSafe" : "IsNotSafe") << std::endl;
    wsss->operation2();
    std::cout << (wsss.isSafe() ? "IsSafe" : "IsNotSafe") << std::endl;

    return 0;
}
