/*
 * 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 <axutil_stack.h>
#include <axutil_utils.h>
#include <axutil_env.h>
#include <stdlib.h>
#include <string.h>

#define AXIS2_STACK_DEFAULT_CAPACITY 10

struct axutil_stack
{
    void **data;

    /** current number of elements */
    int size;

    /** total capacity */
    int capacity;
    axis2_bool_t is_empty_stack;
};

AXIS2_EXTERN axutil_stack_t *AXIS2_CALL
axutil_stack_create(
    const axutil_env_t *env)
{
    axutil_stack_t *stack = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    stack = (axutil_stack_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_stack_t));

    if(!stack)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
        return NULL;
    }

    stack->data = NULL;
    stack->size = 0;
    stack->capacity = AXIS2_STACK_DEFAULT_CAPACITY;
    stack->is_empty_stack = AXIS2_TRUE;

    stack->data = AXIS2_MALLOC(env->allocator, sizeof(void *) * AXIS2_STACK_DEFAULT_CAPACITY);
    if(!stack->data)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
        axutil_stack_free(stack, env);
        return NULL;
    }

    return stack;
}

void AXIS2_CALL
axutil_stack_free(
    axutil_stack_t *stack,
    const axutil_env_t *env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    if(stack->data)
    {
        AXIS2_FREE(env->allocator, stack->data);
    }
    AXIS2_FREE(env->allocator, stack);
    return;
}

void *AXIS2_CALL
axutil_stack_pop(
    axutil_stack_t *stack,
    const axutil_env_t *env)
{
    void *value = NULL;
    AXIS2_ENV_CHECK(env, NULL);

    if(stack->is_empty_stack == AXIS2_TRUE || stack->size == 0)
    {
        return NULL;
    }
    if(stack->size > 0)
    {
        value = stack->data[stack->size - 1];
        stack->data[stack->size - 1] = NULL;
        stack->size--;
        if(stack->size == 0)
        {
            stack->is_empty_stack = AXIS2_TRUE;
        }
    }
    return value;
}

axis2_status_t AXIS2_CALL
axutil_stack_push(
    axutil_stack_t *stack,
    const axutil_env_t *env,
    void *value)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, value, AXIS2_FAILURE);

    if((stack->size < stack->capacity) && (stack->capacity > 0))
    {
        stack->data[stack->size++] = value;
    }
    else
    {
        void **new_data = NULL;

        int new_capacity = stack->capacity + AXIS2_STACK_DEFAULT_CAPACITY;

        new_data = AXIS2_MALLOC(env->allocator, sizeof(void *) * new_capacity);
        if(!new_data)
        {
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
            return AXIS2_FAILURE;
        }
        memset(new_data, 0, sizeof(void *) * new_capacity);
        memcpy(new_data, stack->data, sizeof(void *) * (stack->capacity));
        stack->capacity = new_capacity;

        AXIS2_FREE(env->allocator, stack->data);
        stack->data = new_data;

        stack->data[stack->size++] = value;
    }
    stack->is_empty_stack = AXIS2_FALSE;
    return AXIS2_SUCCESS;
}

int AXIS2_CALL
axutil_stack_size(
    axutil_stack_t *stack,
    const axutil_env_t *env)
{
    return stack->size;
}

void *AXIS2_CALL
axutil_stack_get(
    axutil_stack_t *stack,
    const axutil_env_t *env)
{
    if(stack->size > 0)
    {
        return stack->data[stack->size - 1];
    }
    return NULL;
}

void *AXIS2_CALL
axutil_stack_get_at(
    axutil_stack_t *stack,
    const axutil_env_t *env,
    int i)
{
    if((stack->size == 0) || (i < 0) || (i >= stack->size))
    {
        return NULL;
    }
    return stack->data[i];
}
