/*
 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL). See the LICENSE file in the root
 * directory for license terms. You may choose either license, or both.
 */

#pragma once

#include "iotcs_virtual_device.h"
#include <string>
#include <stdexcept>

/**
 * @file Alert.hpp
 * An Alert to be sent to the server. The alert is sent by calling the
 * raise() method. The time of the alert is set when raise()
 * is called, allowing raise() to be called more than once.
 * <p>
 * The set() method returns the Alert instance to allow
 * the fields of the alert to be set in fluent style.
 * @see VirtualDevice::createAlert(const std::string &)
 */
namespace iotdcl {
    class Alert {
    public:
        /**
         * @brief Destructor
          */
        virtual ~Alert();
        /**
         * @brief Set the value of a field in the {@code Alert}. The fields are
          * determined by the format given when the Alert is created.
          * The value is validated according to the constraints in the format.
          * If the value is not valid, an IllegalArgumentException is raised.
          * <p>All fields defined in the format that are {@code "optional" : true}
          * must be set before calling raise().</p>
          * @param <T> the type of the value.
          * @param attributeName the name of a field from the alert format
          * @param value the value to set
          * @return this Alert instance
          * @see VirtualDevice::createAlert(String)
          * @throw std::invalid_argument if the value is not valid,
          * or attributeName is NULL
          */
        template <typename T> Alert& set(const std::string &attributeName, const T& value) throw(std::invalid_argument);
        /**
         * @brief Send the alert. The event time is set when this method is called.
          * <p>
          * The onError handler of the parent virtual device will be called
          * if there is error sending the alert ***exception is thrown.
          * <p>All fields defined in the format that are {@code "optional" : true}
         * must be set before calling raise(). If raise() is called
         * before setting all {@code "optional" : true} fields, an std::invalid_argument.</p>
         * @throw std::invalid_argument
         */
        void raise(void) throw(std::invalid_argument);
    protected:
        Alert(iotcs_virtual_device_handle handler, const std::string &alertName);
    private:
        Alert();
        iotcs_alert_handle handle;
    };
};
