/*
 * 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_xpath.h>
#include "xpath_streaming.h"
#include "xpath_internals.h"
#include "xpath_internals_engine.h"

axiom_xpath_streaming_t
axiom_xpath_streaming_check_operation(
    const axutil_env_t *env,
    axiom_xpath_expression_t* expr,
    int op_p)
{
    axiom_xpath_operation_t *op;

    if(op_p == AXIOM_XPATH_PARSE_END)
    {
        return AXIOM_XPATH_STREAMING_CONSTANT;
    }

    op = AXIOM_XPATH_OPR_EXPR_GET(op_p);

    switch(op->opr)
    {
        case AXIOM_XPATH_OPERATION_CONTEXT_NODE:
        case AXIOM_XPATH_OPERATION_ROOT_NODE:
            return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_STREAMING_CONSTANT);

        case AXIOM_XPATH_OPERATION_STEP:
            return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_CHECK(op->op2));

        case AXIOM_XPATH_OPERATION_RESULT:
            return AXIOM_XPATH_STREAMING_CONSTANT;

        case AXIOM_XPATH_OPERATION_UNION:
            return axiom_xpath_streaming_combine_independent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_CHECK(op->op2));

        case AXIOM_XPATH_OPERATION_EQUAL_EXPR:
            return axiom_xpath_streaming_combine_independent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_CHECK(op->op2));

        case AXIOM_XPATH_OPERATION_LITERAL:
            return AXIOM_XPATH_STREAMING_CONSTANT;

        case AXIOM_XPATH_OPERATION_NUMBER:
            return AXIOM_XPATH_STREAMING_CONSTANT;

        case AXIOM_XPATH_OPERATION_PATH_EXPRESSION:
            return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_CHECK(op->op2));

        case AXIOM_XPATH_OPERATION_NODE_TEST:
            return axiom_xpath_streaming_check_node_test(env, expr, op);

        case AXIOM_XPATH_OPERATION_PREDICATE:
            return axiom_xpath_streaming_check_predicate(env, expr, op_p);

        default:
#ifdef AXIOM_XPATH_DEBUG
            printf("Unidentified operation.\n");
#endif

            return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }
}

axiom_xpath_streaming_t
axiom_xpath_streaming_check_predicate(
    const axutil_env_t *env,
    axiom_xpath_expression_t* expr,
    int op_p)
{
    axiom_xpath_operation_t *op;

    if(op_p == AXIOM_XPATH_PARSE_END)
    {
        return AXIOM_XPATH_STREAMING_CONSTANT;
    }

    op = AXIOM_XPATH_OPR_EXPR_GET(op_p);

    return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1), AXIOM_XPATH_CHECK(
        op->op2));
}

axiom_xpath_streaming_t
axiom_xpath_streaming_check_node_test(
    const axutil_env_t *env,
    axiom_xpath_expression_t* expr,
    axiom_xpath_operation_t *op)
{
    axiom_xpath_axis_t axis = AXIOM_XPATH_AXIS_NONE;
    axiom_xpath_streaming_t r;

    if(!op->par2)
    {
#ifdef AXIOM_XPATH_DEBUG
        printf("axis is NULL in the step operator\n");
#endif
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }

    axis = *((axiom_xpath_axis_t *)op->par2);

    switch(axis)
    {
        case AXIOM_XPATH_AXIS_ATTRIBUTE:
        case AXIOM_XPATH_AXIS_CHILD:
            break;

        default:
            return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }

    r = axiom_xpath_streaming_check_predicate(env, expr, op->op1);

    if(r != AXIOM_XPATH_STREAMING_ATTRIBUTE && r != AXIOM_XPATH_STREAMING_CONSTANT)
    {
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }

    if(axis == AXIOM_XPATH_AXIS_ATTRIBUTE)
    {
        return AXIOM_XPATH_STREAMING_ATTRIBUTE;
    }
    else
    {
        return AXIOM_XPATH_STREAMING_SUPPORTED;
    }
}

axiom_xpath_streaming_t
axiom_xpath_streaming_combine_dependent(
    axiom_xpath_streaming_t r1,
    axiom_xpath_streaming_t r2)
{
    if(r1 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED)
    {
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }
    else if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
    {
        return AXIOM_XPATH_STREAMING_SUPPORTED;
    }
    else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
    {
        return AXIOM_XPATH_STREAMING_ATTRIBUTE;
    }
    else
    {
        return AXIOM_XPATH_STREAMING_CONSTANT;
    }
}

axiom_xpath_streaming_t
axiom_xpath_streaming_combine_independent(
    axiom_xpath_streaming_t r1,
    axiom_xpath_streaming_t r2)
{
    if(r1 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED)
    {
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }
    else if(r1 == AXIOM_XPATH_STREAMING_CONSTANT || r2 == AXIOM_XPATH_STREAMING_CONSTANT)
    {
        if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
        {
            return AXIOM_XPATH_STREAMING_SUPPORTED;
        }
        else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
        {
            return AXIOM_XPATH_STREAMING_ATTRIBUTE;
        }
        else
        {
            return AXIOM_XPATH_STREAMING_CONSTANT;
        }
    }
    else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
    {
        if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
        {
            return AXIOM_XPATH_STREAMING_SUPPORTED;
        }
        else
        {
            return AXIOM_XPATH_STREAMING_ATTRIBUTE;
        }
    }
    else
    {
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }
}

