#include "../lip_opcua_server_cfg_defs.h"
#if LIP_OPCUA_SERVER_ENABLE
#include "lip_opcua_server_reqproc.h"
#include "lip/app/opcua/types/lip_opcua_nodeid.h"
#include "lip/app/opcua/lip_opcua_std_nodeids.h"
#include "svcsets/lip_opcua_server_svcset_discovery.h"
#include "svcsets/lip_opcua_server_svcset_session.h"
#include "svcsets/lip_opcua_server_svcset_attr.h"
#include "svcsets/lip_opcua_server_svcset_view.h"
#include "svcsets/lip_opcua_server_svcset_monitem.h"
#include "svcsets/lip_opcua_server_svcset_subscription.h"
#include "lip/app/opcua/server/lip_opcua_sc_private.h"






static t_lip_opcua_err f_proc_req_sc_close(struct st_lip_opcua_con *con, const t_lip_opcua_req_info *req, t_lip_proc_buf *data_buf) {
    t_lip_opcua_err err =  LIP_OPCUA_ERR_GOOD;


    uint32_t secureChId;
    err = lip_opcua_procbuf_get_uint32(data_buf, &secureChId);
    if (err == LIP_OPCUA_ERR_GOOD) {
        if (secureChId != lip_opcua_con_sc(con)->cur_token.SecureChannelId) {
            err = LIP_OPCUA_ERR_BAD_CHANNEL_ID_INVALID;
        } else {
            static const t_lip_opcua_nodeid f_resp_node_id = LIP_OPCUA_NODEID_STDNS_INT(LIP_OPCUA_NODEID_STD_CLOSE_SECURE_CHANNEL_RESPONSE_BIN);
            t_lip_proc_buf *resp = lip_opcua_con_resp_prepare(con, &req->resp, &f_resp_node_id, err);
            if (!resp) {
                err = LIP_OPCUA_ERR_BAD_TCP_SERVER_TOO_BUSY;
            } else {
                lip_opcua_con_resp_finish(con, resp);
            }
            lip_opcua_con_sc_close(con);
        }
    }


    return err;
}







t_lip_opcua_err lip_opcua_server_req_process(struct st_lip_opcua_con *con, const t_lip_opcua_req_info *req, t_lip_proc_buf *data_buf) {
    t_lip_opcua_err err = LIP_OPCUA_ERR_GOOD;

    if (lip_opcua_nodeid_check_is_stdns_int(&req->node)) {
        lip_printf(LIP_LOG_MODULE_OPCUA, LIP_LOG_LVL_DEBUG_MEDIUM, 0, "lip opcua: rx std request: id %d, size %d!\n",
                   req->node.intval, lip_procbuf_avsize(data_buf));
        if (req->node.intval == LIP_OPCUA_NODEID_STD_READ_REQUEST_BIN) {
            err = lip_opcua_server_procreq_attr_read(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_WRITE_REQUEST_BIN) {
            err = lip_opcua_server_procreq_attr_write(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_HISTORY_READ_REQUEST_BIN) {
            err = lip_opcua_server_procreq_attr_history_read(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_HISTORY_UPDATE_REQUEST_BIN) {
            err = lip_opcua_server_procreq_attr_history_update(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_BROWSE_REQUEST_BIN) {
            err = lip_opcua_server_procreq_view_browse(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_TRANSLATE_BROWSE_PATHS_TO_NODEIDS_REQUEST_BIN) {
            err = lip_opcua_server_procreq_translate_path(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_REGISTER_NODES_REQUEST_BIN) {
            err = lip_opcua_server_procreq_nodes_register(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_UNREGISTER_NODES_REQUEST_BIN) {
            err = lip_opcua_server_procreq_nodes_unregister(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_CLOSE_SECURE_CHANNEL_REQUEST_BIN) {
            err = f_proc_req_sc_close(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_FIND_SERVERS_REQUEST_BIN) {
            err = lip_opcua_server_procreq_find_servers(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_GET_ENDPOINTS_REQUEST_BIN) {
            err = lip_opcua_server_procreq_get_endpoints(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_CREATE_SESSION_REQUEST_BIN) {
            err = lip_opcua_server_procreq_session_create(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_ACTIVATE_SESSION_REQUEST_BIN) {
            err = lip_opcua_server_procreq_session_activate(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_CLOSE_SESSION_REQUEST_BIN) {
            err = lip_opcua_server_procreq_session_close(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_CREATE_MONITORED_ITEMS_REQUEST_BIN) {
            err = lip_opcua_server_svcset_monitem_create(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_MODIFY_MONITORED_ITEMS_REQUEST_BIN) {
            err = lip_opcua_server_svcset_monitem_modify(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_SET_MONITORING_MODE_REQUEST_BIN) {
            err = lip_opcua_server_svcset_monitem_set_mode(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_SET_TRIGGERING_REQUEST_BIN) {
            err = lip_opcua_server_svcset_monitem_set_trig(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_DELETE_MONITORED_ITEMS_REQUEST_BIN) {
            err = lip_opcua_server_svcset_monitem_delete(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_CREATE_SUBSCRIPTION_REQUEST_BIN) {
            err = lip_opcua_server_procreq_subscription_create(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_MODIFY_SUBSCRIPTION_REQUEST_BIN) {
            err = lip_opcua_server_procreq_subscription_modify(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_SET_PUBLISHING_MODE_REQUEST_BIN) {
            err = lip_opcua_server_procreq_subscription_set_pubmode(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_PUBLISH_REQUEST_BIN) {
            err = lip_opcua_server_procreq_subscription_publish(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_REPUBLISH_REQUEST_BIN) {
            err = lip_opcua_server_procreq_subscription_republish(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_TRANSFER_SUBSCRIPTIONS_REQUEST_BIN) {
            err = lip_opcua_server_procreq_subscription_transfer(con, req, data_buf);
        } else if (req->node.intval == LIP_OPCUA_NODEID_STD_DELETE_SUBSCRIPTIONS_REQUEST_BIN) {
            err = lip_opcua_server_procreq_subscription_delete(con, req, data_buf);
        } else {
            err = LIP_OPCUA_ERR_BAD_SERVICE_UNSUPPORTED;
        }
    } else {
        err = LIP_OPCUA_ERR_BAD_SERVICE_UNSUPPORTED;
    }

    return err;
}

void lip_opcua_server_resp_fault(struct st_lip_opcua_con *con, const t_lip_opcua_req_resp_info *req, t_lip_opcua_err resp_err) {
    static const t_lip_opcua_nodeid f_resp_node_id = LIP_OPCUA_NODEID_STDNS_INT(LIP_OPCUA_NODEID_STD_SERVICE_FAULT_BIN);
    t_lip_proc_buf *resp = lip_opcua_con_resp_prepare(con, req, &f_resp_node_id, resp_err);
    if (resp) {
        lip_opcua_con_resp_finish(con, resp);
    }
}

#endif
