/*
** Copyright 2017-present Open Networking Foundation
**
** 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 <stdio.h>
#include <bal_api.h>

#undef _SYS_QUEUE_H_

#include "asfvolt16_driver.h"
#include "bal_interface_hdlr.h"

/********************************************************************\
 * Function    : bal_interface_cfg_set                              *
 * Description : Configures the PON and NNI interfaces              *
 *               of OLT Device                                      *
 ********************************************************************/
uint32_t bal_interface_cfg_set(BalInterfaceCfg *interface_cfg)
{
    bcmos_errno err = BCM_ERR_OK;
    bcmbal_interface_cfg interface_obj;
    bcmbal_interface_key intf_key;

    intf_key.intf_id = interface_cfg->key->intf_id;
    intf_key.intf_type = interface_cfg->key->intf_type;


    /*
     * Set the key in the interface object and initialize the object itself
     */
    BCMBAL_CFG_INIT(&interface_obj, interface, intf_key);

    bcmbal_cfg_get(DEFAULT_ATERM_ID, &(interface_obj.hdr));

    if(BCMBAL_STATUS_UP != ((bcmbal_interface_cfg *)&interface_obj.hdr)->data.oper_status)
    {
        BCMBAL_CFG_INIT(&interface_obj, interface, intf_key);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, admin_state, BCMOS_TRUE, BCMBAL_STATE_UP);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, min_data_agg_port_id,
                               interface_cfg->data->has_min_data_svc_port_id,
                               interface_cfg->data->min_data_agg_port_id);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, min_data_svc_port_id,
                               interface_cfg->data->has_min_data_svc_port_id,
                               interface_cfg->data->min_data_svc_port_id);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, transceiver_type,
                               BCMOS_TRUE,
                               interface_cfg->data->transceiver_type);
        ASFVOLT_LOG(ASFVOLT_INFO, "Setting transceiver_type to : %d", interface_cfg->data->transceiver_type);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, ds_miss_mode,
                               interface_cfg->data->has_ds_miss_mode,
                               interface_cfg->data->ds_miss_mode);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, mtu,
                               interface_cfg->data->has_mtu,
                               interface_cfg->data->mtu);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, flow_control,
                               interface_cfg->data->has_flow_control,
                               interface_cfg->data->flow_control);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, ds_tm,
                               interface_cfg->data->has_ds_tm,
                               interface_cfg->data->ds_tm);

        ASFVOLT_CFG_PROP_SET(interface_obj, interface, us_tm,
                               interface_cfg->data->has_us_tm,
                               interface_cfg->data->us_tm);

        ASFVOLT_LOG(ASFVOLT_INFO, "Bringing up the interface No: %d", intf_key.intf_id);

        err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));

        if(BCM_ERR_OK != err)
        {
            ASFVOLT_LOG(ASFVOLT_ERROR, "Failed to configure the interface object to ADMIN-UP");
            return BAL_ERRNO__BAL_ERR_INTERNAL;
        }
    }
    ASFVOLT_LOG(ASFVOLT_DEBUG, "Set Interface configuration sent to OLT.Interface ID(%d) Interface Type(%d)",
                                intf_key.intf_id, intf_key.intf_type);
    return BAL_ERRNO__BAL_ERR_OK;
}


/********************************************************************\
 * Function    : bal_interface_cfg_get                              *
 * Description : get the PON and NNI interfaces                     *
 *               of OLT Device                                      *
 ********************************************************************/
uint32_t bal_interface_cfg_get(BalInterfaceKey *interface_cfg_key,
                               BalInterfaceCfg *interface_cfg)
{
    bcmos_errno err = BCM_ERR_OK;
    bcmbal_interface_cfg interface_obj;
    bcmbal_interface_key intf_key;

    if((interface_cfg_key->has_intf_id) && (interface_cfg_key->has_intf_type))
    {
       intf_key.intf_id = interface_cfg_key->intf_id;
       intf_key.intf_type = interface_cfg_key->intf_type;
    }
    else
    {
       ASFVOLT_LOG(ASFVOLT_ERROR, "Failed to get the interface cfg(OLT): Missing Key values "
                                  "Received key values intf-id(%d), intf-type(%d)",
                                   interface_cfg_key->intf_id, interface_cfg_key->intf_type);
       return BAL_ERRNO__BAL_ERR_NOENT;
    }

    ASFVOLT_LOG(ASFVOLT_DEBUG, "Get interface cfg(for OLT) starts");
    /*
     * Set the key in the interface object and initialize the object itself
     */
    BCMBAL_CFG_INIT(&interface_obj, interface, intf_key);

    /* request all properties, include everything */
    BCMBAL_CFG_PROP_GET(&interface_obj, interface, all_properties);

    err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &interface_obj.hdr);

    if(BCM_ERR_OK != err)
    {
        ASFVOLT_LOG(ASFVOLT_ERROR, "Failed to get the interface Cfg(OLT)");
        return BAL_ERRNO__BAL_ERR_INTERNAL;
    }

    ASFVOLT_LOG(ASFVOLT_INFO, "Get Interface cfg sent to OLT. "
                              "Interface ID(%d) Interface Type(%d)",
                               intf_key.intf_id, intf_key.intf_type);
    /* TODO - Add code to call grpc */

    return BAL_ERRNO__BAL_ERR_OK;
}


/********************************************************************\
 * Function    : bal_interface_cfg_clear                            *
 * Description : Clears the PON and NNI interfaces                  *
 *               of OLT Device                                      *
 ********************************************************************/
uint32_t bal_interface_cfg_clear(BalInterfaceKey *interface_cfg_key)
{
    bcmos_errno err = BCM_ERR_OK;
    bcmbal_interface_cfg interface_obj;
    bcmbal_interface_key intf_key;

    if((interface_cfg_key->has_intf_id) && (interface_cfg_key->has_intf_type))
    {
       intf_key.intf_id = interface_cfg_key->intf_id;
       intf_key.intf_type = interface_cfg_key->intf_type;
    }
    else
    {
       ASFVOLT_LOG(ASFVOLT_ERROR, "Failed to clear the interface cfg(OLT): Missing Key values "
                                  "Received key values intf-id(%d), intf-type(%d)",
                                   interface_cfg_key->intf_id, interface_cfg_key->intf_type);
       return BAL_ERRNO__BAL_ERR_NOENT;
    }


    ASFVOLT_LOG(ASFVOLT_DEBUG, "Clearing of OLT(interface cfg) starts");
    /*
     * Set the key in the interface object and initialize the object itself
     */
    BCMBAL_CFG_INIT(&interface_obj, interface, intf_key);

    err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &interface_obj.hdr);

    if(BCM_ERR_OK != err)
    {
        ASFVOLT_LOG(ASFVOLT_ERROR, "Failed to clear the interface Cfg(OLT)");
        return BAL_ERRNO__BAL_ERR_INTERNAL;
    }

    ASFVOLT_LOG(ASFVOLT_INFO, "Clear Interface cfg sent to OLT. "
                              "Interface ID(%d) Interface Type(%d)",
                               intf_key.intf_id, intf_key.intf_type);
    return BAL_ERRNO__BAL_ERR_OK;
}
