/*
** 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_

/* Includes related to proto buf */
#include "asfvolt16_driver.h"
#include "bal_tmsched_hdlr.h"

/********************************************************************\
 * Function    : bal_tm_sched_cfg_set                               *
 * Description : Configures the tm scheduler for OLT device         *
 ********************************************************************/

uint32_t bal_tm_sched_cfg_set(BalTmSchedCfg *tm_sched_cfg)
{
    bcmos_errno err = BCM_ERR_OK;
    bcmbal_tm_sched_cfg tm_sched_obj;   /**< declare main API struct */
    bcmbal_tm_sched_key key = { };      /**< declare key */

    if((tm_sched_cfg->key->has_dir) && (tm_sched_cfg->key->has_id))
    {
       key.dir = tm_sched_cfg->key->dir;
       key.id = tm_sched_cfg->key->id;
    }
    else
    {
       ASFVOLT_LOG(ASFVOLT_ERROR, "Failed to configure the tm schedule cfg(OLT): Missing Key values "
                                  "Received key values Sched-Dir(%d), Sched-Id(%d)",
                                   tm_sched_cfg->key->dir, tm_sched_cfg->key->id);
       return BAL_ERRNO__BAL_ERR_NOENT;
    }

    ASFVOLT_LOG(ASFVOLT_DEBUG, "Configuration of OLT(tm Sched) starts");
    /* init the API struct */
    BCMBAL_CFG_INIT(&tm_sched_obj, tm_sched, key);

    /* decode API parameters from GRPC */
    /* scheduler owner */
    BalTmSchedOwner *tmScOwn = (BalTmSchedOwner *)tm_sched_cfg->data->owner;
    bcmbal_tm_sched_owner valtmScOwn = {};
    if(tmScOwn->has_type)
    {
       valtmScOwn.type = tmScOwn->type;
       switch(valtmScOwn.type)
       {
           case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
              if(tmScOwn->interface->has_intf_type)
              {
                 valtmScOwn.u.interface.intf_type = tmScOwn->interface->intf_type;
              }
              if(tmScOwn->interface->has_intf_id)
              {
                 valtmScOwn.u.interface.intf_id = tmScOwn->interface->intf_id;
              }
              break;
           case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
              if(tmScOwn->sub_term->has_intf_id)
              {
                 valtmScOwn.u.sub_term.intf_id = tmScOwn->sub_term->intf_id;
              }
              if(tmScOwn->sub_term->has_sub_term_id)
              {
                 valtmScOwn.u.sub_term.sub_term_id = tmScOwn->sub_term->sub_term_id;
              }
              break;
           case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
              if(tmScOwn->agg_port->has_presence_mask)
              {
                 valtmScOwn.u.agg_port.presence_mask = tmScOwn->agg_port->presence_mask;
                 if(tmScOwn->agg_port->has_intf_id)
                 {
                    valtmScOwn.u.agg_port.intf_id= tmScOwn->agg_port->intf_id;
                 }
                 if(tmScOwn->agg_port->has_sub_term_id)
                 {
                    valtmScOwn.u.agg_port.sub_term_id = tmScOwn->agg_port->sub_term_id;
                 }
                 if(tmScOwn->agg_port->has_agg_port_id)
                 {
                    valtmScOwn.u.agg_port.agg_port_id = tmScOwn->agg_port->agg_port_id;
                 }
              }
              break;
           case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
              if(tmScOwn->virtual_->has_idx)
              {
                 valtmScOwn.u.virtual.idx = tmScOwn->virtual_->idx;
              }
              break;
           default:
              break;
       }
       ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, owner, BCMOS_TRUE, valtmScOwn);
    }

    ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, sched_type,
                         tm_sched_cfg->data->has_sched_type,
                         tm_sched_cfg->data->sched_type);

    /* scheduler parent */
    BalTmSchedParent *schedPar = (BalTmSchedParent *)tm_sched_cfg->data->sched_parent;
    bcmbal_tm_sched_parent valSchedPar = {};
    if(schedPar != NULL && schedPar->has_presence_mask)
    {
       valSchedPar.presence_mask = schedPar->presence_mask;
       if(schedPar->has_sched_id)
       {
          valSchedPar.sched_id = schedPar->sched_id;
       }
       if(schedPar->has_priority)
       {
          valSchedPar.priority = schedPar->priority;
       }
       if(schedPar->has_weight)
       {
          valSchedPar.weight = schedPar->weight;
       }
       ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, sched_parent, BCMOS_TRUE, valSchedPar);
    }

    /* rating/shaping */
    BalTmShaping *balShaping = (BalTmShaping *)tm_sched_cfg->data->rate;
    bcmbal_tm_shaping val = {};
    if (balShaping != NULL && balShaping->has_presence_mask)
    {
       val.presence_mask = balShaping->presence_mask;
       if (balShaping->has_cir)
       {
          val.cir = balShaping->cir;
       }
       if (balShaping->has_pir)
       {
          val.pir = balShaping->pir;
       }
       if (balShaping->has_burst)
       {
          val.burst = balShaping->burst;
       }
       ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, rate, BCMOS_TRUE, val);
    }

    /* Extended itu dba parameters */
    BalExtendedItuDba *tItuDba = (BalExtendedItuDba *)tm_sched_cfg->data->ext_itu_dba;
    bcmbal_extended_itu_dba valItuDda = {};
    if (tItuDba != NULL && tItuDba->has_presence_mask)
    {
       valItuDda.presence_mask = tItuDba->presence_mask;
       if(tItuDba->has_extra_bw_elig)
       {
          valItuDda.extra_bw_elig = tItuDba->extra_bw_elig;
       }
       if (tItuDba->has_nrt_cbr)
       {
          valItuDda.nrt_cbr = tItuDba->nrt_cbr;
       }
       if (tItuDba->has_rt_cbr)
       {
          valItuDda.rt_cbr = tItuDba->rt_cbr;
       }
       if (tItuDba->has_nrt_profile)
       {
          valItuDda.nrt_profile = tItuDba->nrt_profile;
       }
       if (tItuDba->has_rt_profile)
       {
          valItuDda.rt_profile = tItuDba->rt_profile;
       }
       ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, ext_itu_dba, BCMOS_TRUE, valItuDda);
    }

    /* Creation mode */
    ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, creation_mode,
                         tm_sched_cfg->data->has_creation_mode,
                         tm_sched_cfg->data->creation_mode);

    /* Extended epon dba parameters */
    BalExtendedEponDba *teponDba = (BalExtendedEponDba*)tm_sched_cfg->data->ext_epon_dba;
    bcmbal_extended_epon_dba valeponDda = {};
    if (teponDba != NULL && teponDba->has_presence_mask)
    {
       valeponDda.presence_mask = teponDba->presence_mask;
       if (teponDba->has_polling_interval_us)
       {
          valeponDda.polling_interval_us = teponDba->polling_interval_us;
       }
       if (teponDba->has_grant_threshold_tq)
       {
          valeponDda.grant_threshold_tq = teponDba->grant_threshold_tq;
       }
       if (teponDba->has_cir_priority)
       {
          valeponDda.cir_priority = teponDba->cir_priority;
       }
       if (teponDba->has_cir_weight_tq)
       {
          valeponDda.cir_weight_tq = teponDba->cir_weight_tq;
       }
       if (teponDba->has_pir_priority)
       {
          valeponDda.pir_priority = teponDba->pir_priority;
       }
       if (teponDba->has_pir_weight_tq)
       {
          valeponDda.pir_weight_tq = teponDba->pir_weight_tq;
       }
       if (teponDba->has_tdm_grant_size_tq)
       {
          valeponDda.tdm_grant_size_tq = teponDba->tdm_grant_size_tq;
       }
       if (teponDba->has_tdm_grant_interval_us)
       {
          valeponDda.tdm_grant_interval_us = teponDba->tdm_grant_interval_us;
       }
       ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, ext_epon_dba, BCMOS_TRUE, valeponDda);
    }

    /* Subsidiary queues */
    BalTmQueueIdList *balQueues = (BalTmQueueIdList *)tm_sched_cfg->data->queues;
    bcmbal_tm_queue_id_list_u8 valQueues = {};
    if(balQueues != NULL && balQueues->n_val)
    {
       valQueues.len = balQueues->n_val;
       valQueues.val = (bcmbal_tm_queue_id *)malloc((valQueues.len)*sizeof(bcmbal_tm_queue_id));
       if(!valQueues.val)
       {
          ASFVOLT_LOG(ASFVOLT_ERROR,
                     "Failed to configure the tm scheduler cfg(OLT): Memory Exhausted");
          return BAL_ERRNO__BAL_ERR_NOMEM;
       }
       memcpy((void *)valQueues.val, (const void *)balQueues->val,
              (balQueues->n_val)*sizeof(uint32_t));
       ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, queue_list, BCMOS_TRUE, valQueues);
    }

    /* Subsidiary schedulers */
    BalTmSchedIdList *balSubScheds = (BalTmSchedIdList *)tm_sched_cfg->data->sub_scheds;
    bcmbal_tm_sched_id_list_u8 valSubScheds = {};
    if(balSubScheds != NULL && balSubScheds->n_val)
    {
       valSubScheds.len = balSubScheds->n_val;
       valSubScheds.val = (uint32_t *)malloc((valSubScheds.len)*sizeof(uint32_t));
       if(!valSubScheds.val)
       {
          ASFVOLT_LOG(ASFVOLT_ERROR,
                     "Failed to configure the tm scheduler cfg(OLT): Memory Exhausted");
          return BAL_ERRNO__BAL_ERR_NOMEM;
       }
       memcpy((void *)valSubScheds.val, (const void *)balSubScheds->val,
              (balSubScheds->n_val)*sizeof(uint32_t));
       ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, sub_sched_list, BCMOS_TRUE, valSubScheds);
    }

    ASFVOLT_CFG_PROP_SET(tm_sched_obj, tm_sched, num_priorities,
                         tm_sched_cfg->data->has_num_priorities,
                         tm_sched_cfg->data->num_priorities);

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

    if(BCM_ERR_OK != err)
    {
        ASFVOLT_LOG(ASFVOLT_ERROR, "Failed to configure the tm scheduler Cfg(OLT)");
        return err;
    }

    ASFVOLT_LOG(ASFVOLT_INFO, "Set tm scheduler configuration sent to OLT. "
                              "Sched ID(%d) Sched Dir(%d)", key.id, key.dir);
    return err;
}


/********************************************************************\
 * Function    : bal_tm_sched_cfg_get                               *
 * Description : get the OLT device tm queue configuration          *
 ********************************************************************/

uint32_t bal_tm_sched_cfg_get(BalTmSchedCfg *tm_sched_cfg)
{
    bcmos_errno err = BCM_ERR_OK;
    bcmbal_tm_sched_cfg tm_sched_obj;   /**< declare main API struct */
    bcmbal_tm_sched_key key = { };      /**< declare key */

    key.dir = tm_sched_cfg->key->dir;
    key.id = tm_sched_cfg->key->id;

    ASFVOLT_LOG(ASFVOLT_DEBUG, "Gem tm scheduler cfg (for OLT) starts");

    /* init the API struct */
    BCMBAL_CFG_INIT(&tm_sched_obj, tm_sched, key);

    /* request all properties, include everything */
    BCMBAL_CFG_PROP_GET(&tm_sched_obj, tm_sched, all_properties);

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

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

    ASFVOLT_LOG(ASFVOLT_INFO, "Get tm scheduler cfg sent to OLT. "
                              "Sched ID(%d) Sched Dir(%d)", key.id, key.dir);

    memcpy(tm_sched_cfg->key, &key, sizeof(BalTmSchedKey));
    memcpy(tm_sched_cfg->data, &tm_sched_obj, sizeof(BalTmSchedCfgData));

    return err;
}


/********************************************************************\
 * Function    : bal_tm_sched_cfg_clear                             *
 * Description : Clears the OLT device tm queue configuration       *
 ********************************************************************/

uint32_t bal_tm_sched_cfg_clear(BalTmSchedKey *tm_sched_key)
{
    bcmos_errno err = BCM_ERR_OK;
    bcmbal_tm_sched_cfg tm_sched_obj;   /**< declare main API struct */
    bcmbal_tm_sched_key key = { };      /**< declare key */

    if((tm_sched_key->has_dir) && (tm_sched_key->has_id))
    {
       key.dir = tm_sched_key->dir;
       key.id = tm_sched_key->id;
    }
    else
    {
       ASFVOLT_LOG(ASFVOLT_ERROR, "Failed to clear the tm schedule cfg(OLT): Missing Key values "
                                  "Received key values Sched-Dir(%d), Sched-Id(%d)",
                                   tm_sched_key->dir, tm_sched_key->id);
       return BAL_ERRNO__BAL_ERR_NOENT;
    }

    ASFVOLT_LOG(ASFVOLT_DEBUG, "Clear tm scheduler cfg(for OLT) starts");

    /* init the API struct */
    BCMBAL_CFG_INIT(&tm_sched_obj, tm_sched, key);

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

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

    ASFVOLT_LOG(ASFVOLT_INFO, "Clear tm scheduler clear sent to OLT. "
                              "Sched ID(%d) Sched Dir(%d)", key.id, key.dir);
    return err;
}


/********************************************************************\
 * Function    : bal_tm_sched_indication_cb                         *
 * Description : Call back function registered with BAL to handle   *
 *               event related to access terminal                   *
 ********************************************************************/
bcmos_errno bal_tm_sched_cfg_indication_cb(bcmbal_obj *obj)
{
    bcmos_errno result = BCM_ERR_OK;
    ASFVOLT_LOG(ASFVOLT_INFO, "Processing API (%s) IND callback status is (%s)",
		    bcmbal_objtype_str(obj->obj_type),
		    bcmos_strerror(obj->status));

    return result;
}


