/*
 * Copyright (c) 2021 One Identity
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * As an additional exemption you are allowed to compile & link against the
 * OpenSSL libraries as published by the OpenSSL project. See the file
 * COPYING for details.
 *
 */


%code requires {

#include "mqtt-parser.h"

}

%code {

#include "mqtt-destination.h"
#include "mqtt-source.h"
#include "syslog-names.h"

#include "cfg-grammar-internal.h"
#include "plugin.h"
#include "mqtt-options.h"

MQTTClientOptions *last_options;
}

%define api.prefix {mqtt_}
%lex-param {CfgLexer *lexer}
%parse-param {CfgLexer *lexer}
%parse-param {LogDriver **instance}
%parse-param {gpointer arg}

/* INCLUDE_DECLS */

%token KW_MQTT
%token KW_TOPIC
%token KW_FALLBACK_TOPIC
%token KW_KEEPALIVE
%token KW_ADDRESS
%token KW_QOS
%token KW_CLIENT_ID
%token KW_CLEANSESSION
%token KW_MESSAGE_TEMPLATE
%token KW_USERNAME
%token KW_PASSWORD
%token KW_HTTP_PROXY
%token KW_TLS
%token KW_CA_DIR
%token KW_CA_FILE
%token KW_CERT_FILE
%token KW_KEY_FILE
%token KW_CIPHER_SUITE
%token KW_USE_SYSTEM_CERT_STORE
%token KW_SSL_VERSION
%token KW_PEER_VERIFY

%%

start
        : LL_CONTEXT_DESTINATION KW_MQTT
          {
            last_driver = *instance = mqtt_dd_new(configuration);
            last_options = mqtt_dd_get_options(last_driver);
          }
          '(' mqtt_destination_options ')' { YYACCEPT; }
        | LL_CONTEXT_SOURCE KW_MQTT
          {
            last_driver = *instance = mqtt_sd_new(configuration);
            last_options = mqtt_sd_get_options(last_driver);
          }
          '(' mqtt_source_options ')' { YYACCEPT; }
;

mqtt_destination_options
        : mqtt_destination_option mqtt_destination_options
        |
        ;

mqtt_destination_option
        : threaded_dest_driver_general_option
        | mqtt_option
        | KW_TOPIC '(' template_content ')'     { mqtt_dd_set_topic_template(last_driver, $3);  }
        | KW_FALLBACK_TOPIC '(' string ')'      { mqtt_dd_set_fallback_topic(last_driver, $3); free($3); }
        | KW_TEMPLATE '(' template_content ')'   { mqtt_dd_set_message_template_ref(last_driver, $3); }
        | { last_template_options = mqtt_dd_get_template_options(last_driver); } template_option
        ;

mqtt_source_options
        : mqtt_source_option mqtt_source_options
        | KW_CLEANSESSION '(' yesno ')'          { mqtt_client_options_set_cleansession(last_options, $3); }
        |
        ;

mqtt_source_option
        : threaded_source_driver_option
        | mqtt_option
        | KW_TOPIC '(' string ')' { mqtt_sd_set_topic(last_driver, $3); free($3); }
        ;

mqtt_option
        : KW_KEEPALIVE '(' positive_integer ')' { mqtt_client_options_set_keepalive(last_options, $3);       }
        | KW_ADDRESS '(' string ')'
          {
            CHECK_ERROR(mqtt_client_options_set_address(last_options, $3), @1, "Invalid address");
            free($3);
          }
        | KW_QOS '(' nonnegative_integer ')'
          {
            CHECK_ERROR(0 <= $3 && $3 <= 2, @1, "Allowed QOS values: 0, 1, 2");
            mqtt_client_options_set_qos(last_options, $3);
          }
        | KW_CLIENT_ID '(' string ')'            { CHECK_ERROR(mqtt_client_options_set_client_id(last_options, $3), @3, "mqtt: client_id can't be empty"); free($3); }
        | KW_USERNAME '(' string ')'             { mqtt_client_options_set_username(last_options, $3); free($3); }
        | KW_PASSWORD '(' string ')'             { mqtt_client_options_set_password(last_options, $3); free($3); }
        | KW_HTTP_PROXY '(' string ')'           { mqtt_client_options_set_http_proxy(last_options, $3); free($3); }
        | KW_TLS '(' mqtt_tls_options ')'
        ;

mqtt_tls_options
    : mqtt_tls_option mqtt_tls_options
    |
    ;

mqtt_tls_option
    : KW_CA_DIR     '(' string ')'            { mqtt_client_options_set_ca_dir(last_options, $3); free($3); }
    | KW_CA_FILE    '(' path_check ')'        { mqtt_client_options_set_ca_file(last_options, $3); free($3); }
    | KW_CERT_FILE  '(' path_check ')'        { mqtt_client_options_set_cert_file(last_options, $3); free($3); }
    | KW_KEY_FILE   '(' path_secret ')'       { mqtt_client_options_set_key_file(last_options, $3); free($3); }
    | KW_CIPHER_SUITE '(' string ')'          { mqtt_client_options_set_cipher_suite(last_options, $3); free($3); }
    | KW_SSL_VERSION '(' string ')'           { CHECK_ERROR(mqtt_client_options_set_ssl_version(last_options, $3), @3,
                                                            "mqtt: unsupported SSL version: %s", $3);
                                                free($3); }
    | KW_PEER_VERIFY '(' yesno ')'            { mqtt_client_options_set_peer_verify(last_options, $3); }
    | KW_USE_SYSTEM_CERT_STORE '(' yesno ')'  { mqtt_client_options_use_system_cert_store(last_options, $3); }
    ;

/* INCLUDE_RULES */

%%
