
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <axiom_children_with_specific_attribute_iterator.h>
#include <axiom_attribute.h>
#include <axiom_element.h>

struct axiom_children_with_specific_attribute_iterator
{
    axiom_node_t *current_child;
    axiom_node_t *last_child;
    axis2_bool_t next_called;
    axis2_bool_t remove_called;
    axutil_qname_t *attr_qname;
    axis2_char_t *attr_value;
    axis2_bool_t detach;
};

AXIS2_EXTERN axiom_children_with_specific_attribute_iterator_t *AXIS2_CALL
axiom_children_with_specific_attribute_iterator_create(
    const axutil_env_t * env,
    axiom_node_t * current_child,
    axutil_qname_t * attr_qname,
    axis2_char_t * attr_value,
    axis2_bool_t detach)
{
    axiom_children_with_specific_attribute_iterator_t *iterator = NULL;

    AXIS2_PARAM_CHECK(env->error, current_child, NULL);
    AXIS2_PARAM_CHECK(env->error, attr_qname, NULL);
    AXIS2_PARAM_CHECK(env->error, attr_value, NULL);
    iterator = (axiom_children_with_specific_attribute_iterator_t *)
        AXIS2_MALLOC(env->allocator,
                     sizeof(axiom_children_with_specific_attribute_iterator_t));

    if (!iterator)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    iterator->current_child = NULL;
    iterator->last_child = NULL;

    iterator->next_called = AXIS2_FALSE;
    iterator->remove_called = AXIS2_FALSE;

    iterator->attr_qname = axutil_qname_clone(attr_qname, env);
    iterator->attr_value = attr_value;
    iterator->detach = detach;

    return iterator;
}

AXIS2_EXTERN void AXIS2_CALL
axiom_children_with_specific_attribute_iterator_free(
    axiom_children_with_specific_attribute_iterator_t * iterator,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, void);
    if (iterator->attr_qname)
    {
        axutil_qname_free(iterator->attr_qname, env);
    }
    AXIS2_FREE(env->allocator, iterator);
    return;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_children_with_specific_attribute_iterator_remove(
    axiom_children_with_specific_attribute_iterator_t * iterator,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, iterator, AXIS2_FAILURE);

    if (!(iterator->next_called))
    {
        AXIS2_ERROR_SET(env->error,
                        AXIS2_ERROR_ITERATOR_NEXT_METHOD_HAS_NOT_YET_BEEN_CALLED,
                        AXIS2_FAILURE);
        return AXIS2_FAILURE;
    }
    if (iterator->remove_called)
    {
        AXIS2_ERROR_SET(env->error,
                        AXIS2_ERROR_ITERATOR_REMOVE_HAS_ALREADY_BEING_CALLED,
                        AXIS2_FAILURE);
        return AXIS2_FAILURE;
    }
    iterator->remove_called = AXIS2_TRUE;

    if (!(iterator->last_child))
        return AXIS2_FAILURE;
    axiom_node_free_tree(iterator->last_child, env);
    iterator->last_child = NULL;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
axiom_children_with_specific_attribute_iterator_has_next(
    axiom_children_with_specific_attribute_iterator_t * iterator,
    const axutil_env_t * env)
{
    axis2_bool_t matching_node_found = AXIS2_FALSE;
    axis2_bool_t need_to_move_forward = AXIS2_TRUE;
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    if (!(iterator->current_child))
    {
        return AXIS2_FALSE;
    }
    while (need_to_move_forward)
    {
        if (axiom_node_get_node_type(iterator->current_child, env)
            == AXIOM_ELEMENT)
        {
            axiom_attribute_t *om_attr = NULL;
            axiom_element_t *om_ele = NULL;
            om_ele =
                (axiom_element_t *) axiom_node_get_data_element(iterator->
                                                                current_child,
                                                                env);
            om_attr =
                axiom_element_get_attribute(om_ele, env, iterator->attr_qname);
            break;
            /*if (om_attr &&
                (axutil_strcmp(axiom_attribute_get_value(om_attr, env),
                               iterator->attr_value) == 0))
            {
                matching_node_found = AXIS2_TRUE;
                need_to_move_forward = AXIS2_FALSE;
            }
            else
            {
                iterator->current_child =
                    axiom_node_get_next_sibling(iterator->current_child, env);
                need_to_move_forward = (iterator->current_child != NULL);

            }*/
        }
        else
        {

            iterator->current_child =
                axiom_node_get_next_sibling(iterator->current_child, env);
            need_to_move_forward = (iterator->current_child != NULL);
        }

    }
    return matching_node_found;
}

AXIS2_EXTERN axiom_node_t *AXIS2_CALL
axiom_children_with_specific_attribute_iterator_next(
    axiom_children_with_specific_attribute_iterator_t * iterator,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, NULL);
    AXIS2_PARAM_CHECK(env->error, iterator, NULL);

    iterator->next_called = AXIS2_TRUE;
    iterator->remove_called = AXIS2_FALSE;
    iterator->last_child = iterator->current_child;
    iterator->current_child =
        axiom_node_get_next_sibling(iterator->current_child, env);
    if (iterator->last_child && iterator->detach &&
        (axiom_node_get_parent(iterator->last_child, env)))
    {
        axiom_node_free_tree(iterator->last_child, env);
    }
    return iterator->last_child;
}
