/*
<:copyright-BRCM:2016:DUAL/GPL:standard

   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
   All Rights Reserved

Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:

   As a special exception, the copyright holders of this software give
   you permission to link this software with independent modules, and
   to copy and distribute the resulting executable under terms of your
   choice, provided that you also meet, for each linked independent
   module, the terms and conditions of the license of that module.
   An independent module is a module which is not derived from this
   software.  The special exception does not apply to any modifications
   of the software.

Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.

:>
*/

#include <bcmos_system.h>
#include <bcmolt_api.h>
#include <bcmolt_model_types.h>
#include <bcm_dev_log.h>
#include <bcmos_common.h>
#include "bcmolt_user_appl_ps.h"
#include "bcmolt_user_appl_ps_internal.h"


static bcmos_errno ps_handle_ni_no_reports(bcmolt_ps_global_cfg * global_cfg, const bcmolt_ps_pon *pon, const bcmolt_epon_ni_no_reports * ind)
{
    if (ind->data.alarm_status == BCMOLT_STATUS_OFF)
    {
        PS_INFO("<%d:%d> LoS alarm cleared\n", pon->device_id, pon->pon_id);
        return BCM_ERR_OK;
    }

    PS_INFO("<%d:%d> LoS alarm raised\n", pon->device_id, pon->pon_id);

    if (global_cfg->switch_condition == BCMOLT_PS_SWITCH_CONDITION_MANUAL)
    {
        /* don't react to the switch if we're in manual switch mode */
        return BCM_ERR_OK;
    }
    else
    {
        return bcmolt_ps_switch_perform(pon);
    }
}

static bcmos_errno ps_handle_logical_link_discovered(bcmolt_ps_global_cfg * global_cfg, const bcmolt_ps_pon *pon, const bcmolt_epon_link_mpcp_discovered * ind)
{
    bcmolt_ps_pon_state state;
    bcmolt_ps_pon partner;
    bcmos_errno result;

    if (global_cfg->mirror_mode != BCMOLT_PS_MIRROR_MODE_AUTO)
    {
        return BCM_ERR_OK;
    }
    
    //At this point we know we have a link discovered on a PON that is in the PROTECTED WORKING state.
    //This means we want to make sure that is is setup on the PROCTECTED STANDBY PON.  It is possible
    //That this link has been previously configured on the STANDBY PON so we have to handle that case
    //gracefully as well.
    result = bcmolt_ps_pon_state_get(pon, &state, &partner);
    PS_INFO("pon %d, bcmolt_ps_pon_state_get result == %d, state == %d, partner.pon_id == %d\n", pon->pon_id, result, state, partner.pon_id);
    if ((BCM_ERR_OK == result) && (state == BCMOLT_PS_PON_STATE_WORKING))
    {
        bcmolt_epon_ni_add_protected_standby_link add_standby = {};
        bcmolt_epon_ni_key key = {};
        PS_INFO("Mirroring received link discovered on working PON\n");

        key.epon_ni = (bcmolt_epon_ni)partner.pon_id;  //Setup the standby PON as the location to add the link.
        
        //Setup operation key for api call.
        BCMOLT_OPER_INIT(&add_standby, epon_ni, add_protected_standby_link, key);

        //Copy over the data from the received messages:
        BCMOLT_OPER_PROP_SET(&add_standby, epon_ni, add_protected_standby_link, mac_address, ind->key.mac_address);
        BCMOLT_OPER_PROP_SET(&add_standby, epon_ni, add_protected_standby_link, working_link_info, ind->data.link_info);

        result = bcmolt_oper_submit(partner.device_id, &add_standby.hdr);

        //We have multiple acceptable return codes here:  
        //  BCM_ERR_OK      - Indicates new entry created.
        //  BCM_ERR_ALREADY - Indicates the entry already exists (possible after deregistration/reregistration).
        PS_INFO("Mirroring add protected standby link result %d\n", result);

        if ( (result == BCM_ERR_OK) || (result == BCM_ERR_ALREADY) )
        {
            bcmolt_epon_link_static_registration static_reg = {};
            bcmolt_epon_link_key link_key = {};

            link_key.epon_ni = (bcmolt_epon_ni)partner.pon_id;
            link_key.mac_address = ind->key.mac_address;

            //Setup operation key for api call.
            BCMOLT_OPER_INIT(&static_reg, epon_link, static_registration, link_key);
            BCMOLT_OPER_PROP_SET(&static_reg, epon_link, static_registration, laseron_time_tq, ind->data.link_info.onu_laser_on_time_tq);
            BCMOLT_OPER_PROP_SET(&static_reg, epon_link, static_registration, laseroff_time_tq, ind->data.link_info.onu_laser_off_time_tq);
            BCMOLT_OPER_PROP_SET(&static_reg, epon_link, static_registration, range_value_tq, ind->data.link_info.range_value_tq);
            BCMOLT_OPER_PROP_SET(&static_reg, epon_link, static_registration, pending_grants, ind->data.link_info.pending_grants);
            result = bcmolt_oper_submit(partner.device_id, &static_reg.hdr);
            if (result != BCM_ERR_OK)
            {
                PS_ERR("Static registration failed %d\n", result);
            }
            else
            {
                PS_INFO("Static registration success\n");
            }
        }
        else
        {
            PS_ERR("Add protected standby failed %d\n", result);
        }
    }
    return BCM_ERR_OK;
}

bcmos_errno ps_process_ind_epon(const bcmolt_ps_pon *pon, const bcmolt_auto *ind)
{
    bcmos_errno err;
    bcmolt_ps_global_cfg global_cfg;

    err = bcmolt_ps_global_cfg_get(&global_cfg);
    if (err != BCM_ERR_OK)
    {
        return err;
    }

    PS_INFO("ps_process_ind_epon Type: %d CFG_ID: %d\n", ind->hdr.obj_type, ind->hdr.subgroup);
    switch (ind->hdr.obj_type)
    {
    case BCMOLT_OBJ_ID_EPON_NI:
        switch (ind->hdr.subgroup)
        {
        case BCMOLT_EPON_NI_AUTO_CFG_ID_NO_REPORTS:
            return ps_handle_ni_no_reports(&global_cfg, pon, ((const bcmolt_epon_ni_no_reports *)ind));
        default:
            return BCM_ERR_OK;
        }
    case BCMOLT_OBJ_ID_EPON_LINK:
        switch (ind->hdr.subgroup)
        {
        case BCMOLT_EPON_LINK_AUTO_CFG_ID_MPCP_DISCOVERED:
            return ps_handle_logical_link_discovered(&global_cfg, pon, ((const bcmolt_epon_link_mpcp_discovered *)ind));
        default:
            return BCM_ERR_OK;
        }
    default:
        return BCM_ERR_OK;
    }

    return BCM_ERR_OK;
}

bcmos_errno ps_move_to_standby_epon(const bcmolt_ps_pon *pon)
{
    bcmolt_epon_ni_set_epon_ni_en_state set_pon_state; 
    bcmolt_epon_ni_key key = {};
    key.epon_ni = pon->pon_id;

    BCMOLT_OPER_INIT(&set_pon_state, epon_ni, set_epon_ni_en_state, key);
    BCMOLT_OPER_PROP_SET(&set_pon_state, epon_ni, set_epon_ni_en_state, new_state, BCMOLT_EPON_NI_EN_STATE_PROTECTED_STANDBY);
    return bcmolt_oper_submit(pon->device_id, &set_pon_state.hdr);
}

bcmos_errno ps_move_to_working_epon(const bcmolt_ps_pon *pon)
{
    bcmolt_epon_ni_set_epon_ni_en_state set_pon_state;
    bcmolt_epon_ni_key key = {};
    key.epon_ni = pon->pon_id;

    BCMOLT_OPER_INIT(&set_pon_state, epon_ni, set_epon_ni_en_state, key);
    BCMOLT_OPER_PROP_SET(&set_pon_state, epon_ni, set_epon_ni_en_state, new_state, BCMOLT_EPON_NI_EN_STATE_PROTECTED_WORKING);
    return bcmolt_oper_submit(pon->device_id, &set_pon_state.hdr);
}