/**
 * champlain_map_source_chain_pop:
 * @source_chain: a #ChamplainMapSourceChain
 *
 * Pops a map source from the top of the stack from the chain.
 *
 * Since: 0.6
 */
void
champlain_map_source_chain_pop (ChamplainMapSourceChain *source_chain)
{
  ChamplainMapSourceChainPrivate *priv = source_chain->priv;
  ChamplainMapSource *old_stack_top = priv->stack_top;
  ChamplainMapSource *next_source = champlain_map_source_get_next_source (priv->stack_top);

  g_return_if_fail (priv->stack_top);

  if (CHAMPLAIN_IS_TILE_CACHE (priv->stack_top))
    {
      ChamplainTileCache *tile_cache = NULL;

      if (CHAMPLAIN_IS_TILE_CACHE (next_source))
        tile_cache = CHAMPLAIN_TILE_CACHE (next_source);

      /* _push() guarantees that the last source is tile_source so we can be
         sure that the next map source is still within the chain */
      assign_cache_of_next_source_sequence (source_chain, priv->stack_top, tile_cache);
    }

  if (next_source == champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE (source_chain)))
    {
      priv->stack_top = NULL;
      priv->stack_bottom = NULL;
    }
  else
    priv->stack_top = next_source;

  g_object_unref (old_stack_top);
}
/**
 * champlain_map_source_chain_push:
 * @source_chain: a #ChamplainMapSourceChain
 * @map_source: the #ChamplainMapSource to be pushed into the chain
 *
 * Pushes a map source into the chain.
 *
 * Since: 0.6
 */
void
champlain_map_source_chain_push (ChamplainMapSourceChain *source_chain,
    ChamplainMapSource *map_source)
{
  ChamplainMapSourceChainPrivate *priv = source_chain->priv;
  gboolean is_cache = FALSE;

  if (CHAMPLAIN_IS_TILE_CACHE(map_source))
    is_cache = TRUE;
  else
    g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE(map_source));

  g_object_ref_sink (map_source);

  if (!priv->stack_top)
    {
      ChamplainMapSource *chain_next_source = champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE(source_chain));

      /* tile source has to be last */
      g_return_if_fail (!is_cache);

      priv->stack_top = map_source;
      priv->stack_bottom = map_source;
      if (chain_next_source)
        champlain_map_source_set_next_source (priv->stack_bottom, chain_next_source);
    }
  else
    {
      if (g_signal_handler_is_connected (priv->stack_top, priv->sig_handler_id))
        g_signal_handler_disconnect (priv->stack_top, priv->sig_handler_id);

      champlain_map_source_set_next_source (map_source, priv->stack_top);
      priv->stack_top = map_source;

      if (is_cache)
        {
          ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(map_source);
          assign_cache_of_next_source_sequence (source_chain, priv->stack_top, tile_cache);
        }
    }

  priv->sig_handler_id = g_signal_connect (priv->stack_top, "reload-tiles",
                         G_CALLBACK (reload_tiles_cb), source_chain);
}
/**
 * champlain_map_source_chain_pop:
 * @source_chain: a #ChamplainMapSourceChain
 *
 * Pops the map source from the top of the stack from the chain.
 *
 * Since: 0.6
 */
void
champlain_map_source_chain_pop (ChamplainMapSourceChain *source_chain)
{
  ChamplainMapSourceChainPrivate *priv = source_chain->priv;
  ChamplainMapSource *old_stack_top = priv->stack_top;
  ChamplainMapSource *next_source = champlain_map_source_get_next_source (priv->stack_top);

  g_return_if_fail (priv->stack_top);

  if (g_signal_handler_is_connected (priv->stack_top, priv->sig_handler_id))
    g_signal_handler_disconnect (priv->stack_top, priv->sig_handler_id);

  if (CHAMPLAIN_IS_TILE_CACHE(priv->stack_top))
    {
      ChamplainTileCache *tile_cache = NULL;

      if (CHAMPLAIN_IS_TILE_CACHE(next_source))
        tile_cache = CHAMPLAIN_TILE_CACHE(next_source);

      /* _push() guarantees that the last source is tile_source so we can be
         sure that the next map source is still within the chain */
      assign_cache_of_next_source_sequence (source_chain, priv->stack_top, tile_cache);
    }

  if (next_source == champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE(source_chain)))
  {
    priv->stack_top = NULL;
    priv->stack_bottom = NULL;
  }
  else
    priv->stack_top = next_source;

  if (priv->stack_top)
    {
      priv->sig_handler_id = g_signal_connect (priv->stack_top, "reload-tiles",
                             G_CALLBACK (reload_tiles_cb), source_chain);
    }

  g_object_unref (old_stack_top);
}
/**
 * champlain_map_source_chain_push:
 * @source_chain: a #ChamplainMapSourceChain
 * @map_source: the #ChamplainMapSource to be pushed into the chain
 *
 * Pushes a map source into the chain.
 *
 * Since: 0.6
 */
void
champlain_map_source_chain_push (ChamplainMapSourceChain *source_chain,
    ChamplainMapSource *map_source)
{
  ChamplainMapSourceChainPrivate *priv = source_chain->priv;
  gboolean is_cache = FALSE;

  if (CHAMPLAIN_IS_TILE_CACHE (map_source))
    is_cache = TRUE;
  else
    g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source));

  g_object_ref_sink (map_source);

  if (!priv->stack_top)
    {
      ChamplainMapSource *chain_next_source = champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE (source_chain));

      /* tile source has to be last */
      g_return_if_fail (!is_cache);

      priv->stack_top = map_source;
      priv->stack_bottom = map_source;
      if (chain_next_source)
        champlain_map_source_set_next_source (priv->stack_bottom, chain_next_source);
    }
  else
    {
      champlain_map_source_set_next_source (map_source, priv->stack_top);
      priv->stack_top = map_source;

      if (is_cache)
        {
          ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE (map_source);
          assign_cache_of_next_source_sequence (source_chain, priv->stack_top, tile_cache);
        }
    }
}