/* this file is part of papers, a gnome document viewer
 *
 *  Copyright (C) 2022 Qiu Wenbo
 *
 * Papers 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.
 *
 * Papers 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.
 */

#include "pps-outlines.h"

struct _PpsOutlinesPrivate {
	gchar *markup;
	gchar *label;
	gboolean expand;
	PpsLink *link;
	GListModel *children;
};

typedef struct _PpsOutlinesPrivate PpsOutlinesPrivate;
#define GET_PRIVATE(o) pps_outlines_get_instance_private (o)

G_DEFINE_TYPE_WITH_PRIVATE (PpsOutlines, pps_outlines, G_TYPE_OBJECT)

enum {
	PROP_0,
	PROP_MARKUP,
	PROP_LABEL,
	PROP_EXPAND,
	PROP_CHILDREN,
	PROP_LINK,
};

void
pps_outlines_set_markup (PpsOutlines *pps_outlines,
                         const gchar *markup)
{
	PpsOutlinesPrivate *priv = GET_PRIVATE (pps_outlines);

	priv->markup = g_strdup (markup);

	g_object_notify (G_OBJECT (pps_outlines), "markup");
}

void
pps_outlines_set_label (PpsOutlines *pps_outlines,
                        const gchar *label)
{
	PpsOutlinesPrivate *priv = GET_PRIVATE (pps_outlines);

	priv->label = g_strdup (label);

	g_object_notify (G_OBJECT (pps_outlines), "label");
}

static void
pps_outlines_set_property (GObject *object,
                           guint prop_id,
                           const GValue *value,
                           GParamSpec *pspec)
{
	PpsOutlines *outlines = PPS_OUTLINES (object);
	PpsOutlinesPrivate *priv = GET_PRIVATE (outlines);

	switch (prop_id) {
	case PROP_MARKUP:
		pps_outlines_set_markup (outlines,
		                         g_value_get_string (value));
		break;
	case PROP_LABEL:
		pps_outlines_set_label (outlines,
		                        g_value_get_string (value));
		break;
	case PROP_EXPAND:
		priv->expand = g_value_get_boolean (value);
		break;
	case PROP_CHILDREN:
		priv->children = g_value_get_object (value);
		break;
	case PROP_LINK:
		priv->link = g_object_ref (g_value_get_object (value));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

/**
 * pps_outlines_get_link
 * @pps_outlines: A #PpsOutlines
 *
 * Returns: (transfer none) (nullable): The #PpsLink of the outlines
 */
PpsLink *
pps_outlines_get_link (PpsOutlines *pps_outlines)
{
	PpsOutlinesPrivate *priv = GET_PRIVATE (pps_outlines);
	g_return_val_if_fail (PPS_IS_OUTLINES (pps_outlines), NULL);

	return priv->link;
}

/**
 * pps_outlines_set_expand:
 * @pps_outlines: A #PpsOutlines
 * @expand: Whether the outlines should be expanded
 *
 * Sets the 'expand' property of the outlines.
 */
void
pps_outlines_set_expand (PpsOutlines *pps_outlines, gboolean expand)
{
	PpsOutlinesPrivate *priv = GET_PRIVATE (pps_outlines);
	g_return_if_fail (PPS_IS_OUTLINES (pps_outlines));

	priv->expand = expand;
	g_object_notify (G_OBJECT (pps_outlines), "expand");
}

/**
 * pps_outlines_get_expand:
 * @pps_outlines: A #PpsOutlines
 *
 *
 * Returns: Whether the outlines should be expanded
 */
gboolean
pps_outlines_get_expand (PpsOutlines *pps_outlines)
{
	g_return_val_if_fail (PPS_IS_OUTLINES (pps_outlines), FALSE);

	PpsOutlinesPrivate *priv = GET_PRIVATE (pps_outlines);
	return priv->expand;
}

/**
 * pps_outlines_set_children:
 * @pps_outlines: A #PpsOutlines
 * @children: (transfer full): The children of the outlines
 *
 * Sets the 'children' property of the outlines.
 */
void
pps_outlines_set_children (PpsOutlines *pps_outlines, GListModel *children)
{
	PpsOutlinesPrivate *priv = GET_PRIVATE (pps_outlines);
	g_return_if_fail (PPS_IS_OUTLINES (pps_outlines));

	if (g_set_object (&priv->children, children))
		g_object_notify (G_OBJECT (pps_outlines), "children");
}

/**
 * pps_outlines_get_children:
 * @pps_outlines: A #PpsOutlines
 *
 * Returns: (nullable) (transfer none): The children of the outlines
 */
GListModel *
pps_outlines_get_children (PpsOutlines *pps_outlines)
{
	PpsOutlinesPrivate *priv = GET_PRIVATE (pps_outlines);
	g_return_val_if_fail (PPS_IS_OUTLINES (pps_outlines), NULL);

	return priv->children;
}

static void
pps_outlines_get_property (GObject *object,
                           guint prop_id,
                           GValue *value,
                           GParamSpec *pspec)
{
	PpsOutlines *outlines = PPS_OUTLINES (object);
	PpsOutlinesPrivate *priv = GET_PRIVATE (outlines);

	switch (prop_id) {
	case PROP_MARKUP:
		g_value_set_string (value, priv->markup);
		break;
	case PROP_LABEL:
		g_value_set_string (value, priv->label);
		break;
	case PROP_EXPAND:
		g_value_set_boolean (value, priv->expand);
		break;
	case PROP_CHILDREN:
		g_value_set_object (value, priv->children);
		break;
	case PROP_LINK:
		g_value_set_object (value, priv->link);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
pps_outlines_dispose (GObject *object)
{
	PpsOutlines *outlines = PPS_OUTLINES (object);
	PpsOutlinesPrivate *priv = GET_PRIVATE (outlines);

	g_free (priv->markup);
	g_free (priv->label);
	g_clear_object (&priv->children);
	g_clear_object (&priv->link);

	G_OBJECT_CLASS (pps_outlines_parent_class)->dispose (object);
}

static void
pps_outlines_init (PpsOutlines *pps_outlines)
{
}

static void
pps_outlines_class_init (PpsOutlinesClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS (klass);

	object_class->set_property = pps_outlines_set_property;
	object_class->get_property = pps_outlines_get_property;
	object_class->dispose = pps_outlines_dispose;

	g_object_class_install_property (object_class,
	                                 PROP_MARKUP,
	                                 g_param_spec_string ("markup",
	                                                      "markup",
	                                                      "The markup of the outlines",
	                                                      NULL,
	                                                      G_PARAM_READWRITE |
	                                                          G_PARAM_STATIC_STRINGS));

	g_object_class_install_property (object_class,
	                                 PROP_LABEL,
	                                 g_param_spec_string ("label",
	                                                      "Label",
	                                                      "The label of the outlines",
	                                                      NULL,
	                                                      G_PARAM_READWRITE |
	                                                          G_PARAM_STATIC_STRINGS));

	g_object_class_install_property (object_class,
	                                 PROP_EXPAND,
	                                 g_param_spec_boolean ("expand",
	                                                       "expand",
	                                                       "Whether the outlines should be expanded",
	                                                       FALSE,
	                                                       G_PARAM_READWRITE |
	                                                           G_PARAM_STATIC_STRINGS));

	g_object_class_install_property (object_class,
	                                 PROP_CHILDREN,
	                                 g_param_spec_object ("children",
	                                                      "Children",
	                                                      "The children of the outlines",
	                                                      G_TYPE_LIST_MODEL,
	                                                      G_PARAM_READWRITE));

	g_object_class_install_property (object_class,
	                                 PROP_LINK,
	                                 g_param_spec_object ("link",
	                                                      "Link",
	                                                      "The link of the outlines",
	                                                      PPS_TYPE_LINK,
	                                                      G_PARAM_READWRITE));
}
