/*
 * Copyright (c) 2016 Cisco and/or its affiliates.
 * Licensed 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 <vnet/adj/adj_delegate.h>
#include <vnet/adj/adj.h>
#include <vnet/adj/adj_internal.h>

/*
 * The per-type vector of virtual function tables
 */
static adj_delegate_vft_t *ad_vfts;

/**
 * The value of the last dynamically allocated delegate value
 */
static adj_delegate_type_t ad_max_id = ADJ_DELEGATE_LAST;

static adj_delegate_t *
adj_delegate_find_i (const ip_adjacency_t *adj,
                     adj_delegate_type_t type,
                     u32 *index)
{
    adj_delegate_t *delegate;
    int ii;

    ii = 0;
    vec_foreach(delegate, adj->ia_delegates)
    {
	if (delegate->ad_type == type)
	{
            if (NULL != index)
                *index = ii;

	    return (delegate);
	}
	else
	{
	    ii++;
	}
    }

    return (NULL);
}

adj_delegate_t *
adj_delegate_get (const ip_adjacency_t *adj,
                  adj_delegate_type_t type)
{
    return (adj_delegate_find_i(adj, type, NULL));
}

void
adj_delegate_remove (adj_index_t ai,
                     adj_delegate_type_t type)
{
    ip_adjacency_t *adj;
    adj_delegate_t *aed;
    u32 index = ~0;

    adj = adj_get(ai);
    aed = adj_delegate_find_i(adj, type, &index);

    ASSERT(NULL != aed);

    vec_del1(adj->ia_delegates, index);
}

static int
adj_delegate_cmp_for_sort (void * v1,
                           void * v2)
{
    adj_delegate_t *aed1 = v1, *aed2 = v2;

    return (aed1->ad_type - aed2->ad_type);
}

static void
adj_delegate_init (ip_adjacency_t *adj,
                   adj_delegate_type_t adt,
                   index_t adi)

{
    adj_delegate_t aed = {
        .ad_adj_index = adj_get_index(adj),
        .ad_type = adt,
        .ad_index = adi,
    };

    vec_add1(adj->ia_delegates, aed);
    vec_sort_with_function(adj->ia_delegates,
			   adj_delegate_cmp_for_sort);
}

int
adj_delegate_add (ip_adjacency_t *adj,
                  adj_delegate_type_t adt,
                  index_t adi)
{
    adj_delegate_t *delegate;

    delegate = adj_delegate_get(adj, adt);

    if (NULL == delegate)
    {
	adj_delegate_init(adj, adt, adi);
    }
    else
    {
        return (-1);
    }

    return (0);
}

void
adj_delegate_adj_modified (ip_adjacency_t *adj)
{
    adj_delegate_t *aed;

    vec_foreach(aed, adj->ia_delegates)
    {
        if (ad_vfts[aed->ad_type].adv_adj_modified)
        {
            ad_vfts[aed->ad_type].adv_adj_modified(aed);
        }
    }
}

void
adj_delegate_adj_deleted (ip_adjacency_t *adj)
{
    adj_delegate_t *aed;

    vec_foreach(aed, adj->ia_delegates)
    {
        if (ad_vfts[aed->ad_type].adv_adj_deleted)
        {
            ad_vfts[aed->ad_type].adv_adj_deleted(aed);
        }
    }

    vec_reset_length(adj->ia_delegates);
}

void
adj_delegate_adj_created (ip_adjacency_t *adj)
{
    adj_delegate_vft_t *vft;

    vec_foreach(vft, ad_vfts)
    {
        if (vft->adv_adj_created)
        {
            vft->adv_adj_created(adj_get_index(adj));
        }
    }
}

u8*
adj_delegate_format (u8* s, ip_adjacency_t *adj)
{
    adj_delegate_t *aed;

    vec_foreach(aed, adj->ia_delegates)
    {
        if (ad_vfts[aed->ad_type].adv_format)
        {
            s = format(s, "\n  {");
            s = ad_vfts[aed->ad_type].adv_format(aed, s);
            s = format(s, "}");
        }
        else
        {
            s = format(s, "\n  {unknown delegate}");
        }
    }

    return (s);
}

/**
 * adj_delegate_register_type
 *
 * Register the function table for a given type
 */
void
adj_delegate_register_type (adj_delegate_type_t type,
			    const adj_delegate_vft_t *vft)
{
    /*
     * assert that one only registration is made per-node type
     */
    if (vec_len(ad_vfts) > type)
        ASSERT(NULL == ad_vfts[type].adv_adj_deleted);

    vec_validate(ad_vfts, type);
    ad_vfts[type] = *vft;
}

/**
 * adj_delegate_register_new_type
 *
 * Register the function table for a new type
 */
adj_delegate_type_t
adj_delegate_register_new_type (const adj_delegate_vft_t *vft)
{
    adj_delegate_type_t type;

    type = ++ad_max_id;

    vec_validate(ad_vfts, type);
    ad_vfts[type] = *vft;

    return (type);
}
