/* poppler-optcontent-private.h: qt interface to poppler
 *
 * Copyright (C) 2007, Brad Hards <bradh@kde.org>
 * Copyright (C) 2008, Pino Toscano <pino@kde.org>
 * Copyright (C) 2016, 2018, 2019, 2021, Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2017, Hubert Figuière <hub@figuiere.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, 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 Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#ifndef POPPLER_OPTCONTENT_PRIVATE_H
#define POPPLER_OPTCONTENT_PRIVATE_H

#include <QtCore/QMap>
#include <QtCore/QSet>
#include <QtCore/QString>

class Array;
class OCGs;
class OptionalContentGroup;

class QModelIndex;

namespace Poppler {
class OptContentItem;
class OptContentModel;
class OptContentModelPrivate;

class RadioButtonGroup
{
public:
    RadioButtonGroup(OptContentModelPrivate *ocModel, Array *rbarray);
    ~RadioButtonGroup();
    QSet<OptContentItem *> setItemOn(OptContentItem *itemToSetOn);

private:
    QList<OptContentItem *> itemsInGroup;
};

class OptContentItem
{
public:
    enum ItemState
    {
        On,
        Off,
        HeadingOnly
    };

    explicit OptContentItem(OptionalContentGroup *group);
    explicit OptContentItem(const QString &label);
    OptContentItem();
    ~OptContentItem();

    QString name() const { return m_name; }
    ItemState state() const { return m_stateBackup; }
    void setState(ItemState state, bool obeyRadioGroups, QSet<OptContentItem *> &changedItems);

    QList<OptContentItem *> childList() { return m_children; }

    void setParent(OptContentItem *parent) { m_parent = parent; }
    OptContentItem *parent() { return m_parent; }

    void addChild(OptContentItem *child);

    void appendRBGroup(RadioButtonGroup *rbgroup);

    bool isEnabled() const { return m_enabled; }

    QSet<OptContentItem *> recurseListChildren(bool includeMe = false) const;

    OptionalContentGroup *group() const { return m_group; }

private:
    OptionalContentGroup *m_group;
    QString m_name;
    ItemState m_state; // true for ON, false for OFF
    ItemState m_stateBackup;
    QList<OptContentItem *> m_children;
    OptContentItem *m_parent;
    QList<RadioButtonGroup *> m_rbGroups;
    bool m_enabled;
};

class OptContentModelPrivate
{
public:
    OptContentModelPrivate(OptContentModel *qq, OCGs *optContent);
    ~OptContentModelPrivate();

    OptContentModelPrivate(const OptContentModelPrivate &) = delete;
    OptContentModelPrivate &operator=(const OptContentModelPrivate &) = delete;

    void parseRBGroupsArray(Array *rBGroupArray);
    OptContentItem *nodeFromIndex(const QModelIndex &index, bool canBeNull = false) const;
    QModelIndex indexFromItem(OptContentItem *node, int column) const;

    /**
       Get the OptContentItem corresponding to a given reference value.

       \param ref the reference number (e.g. from Object.getRefNum()) to look up

       \return the matching optional content item, or null if the reference wasn't found
    */
    OptContentItem *itemFromRef(const QString &ref) const;
    void setRootNode(OptContentItem *node);

    OptContentModel *q;

    QMap<QString, OptContentItem *> m_optContentItems;
    QList<OptContentItem *> m_headerOptContentItems;
    QList<RadioButtonGroup *> m_rbgroups;
    OptContentItem *m_rootNode;

private:
    void addChild(OptContentItem *parent, OptContentItem *child);
    void parseOrderArray(OptContentItem *parentNode, Array *orderArray);
};
}

#endif
