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

#include <vector>
#include <string>
#include <initializer_list>
#include <AbstractVirtualDevice.hpp>
#include <GatewayDevice.hpp>
#include <DirectlyConnectedDevice.hpp>

/* include iot cs device model APIs */
#include "iotcs.h"
#include "iotcs_device.h"
#include "iotcs_virtual_device.h"
#include <device_model/DeviceModelImpl.hpp>
#include <util/CPPUtils.hpp>

#define ENDPOINT_ID_MAX_LEN 255

using namespace std;

namespace iotdcl {
#ifdef IOTCS_GATEWAY

    GatewayDevice::GatewayDevice(const string &filePath, const string &password) throw (std::invalid_argument, GeneralException) : DirectlyConnectedDevice(filePath, password) {

    }

    GatewayDevice::~GatewayDevice() {
    }

    string GatewayDevice::registerDevice(const bool restricted,
            const string &hardwareId,
            const map<string, string> &metaData,
            const initializer_list<string> &urns) throw (GeneralException, CanNotAuthorizeException, std::invalid_argument) {
        vector<string> deviceModelUrls(urns);
        char *temp_endpoint_id = new char[ENDPOINT_ID_MAX_LEN];

        iotcs_key_value *temp_metadata = new iotcs_key_value[metaData.size() + 1];

        unsigned int i = 0;
        for (map<string, string>::const_iterator it = metaData.begin(); it != metaData.end(); ++i, ++it) {
            temp_metadata[i].key = it->first.c_str();
            temp_metadata[i].value = it->second.c_str();
        }
        temp_metadata[i].key = NULL;
        temp_metadata[i].value = NULL;

        const char **device_models = new const char*[deviceModelUrls.size() + 1];

        for (i = 0; i < deviceModelUrls.size(); ++i) {
            device_models[i] = deviceModelUrls[i].c_str();
        }
        device_models[i] = NULL;


        iotcs_result rv = iotcs_register_device((iotcs_bool) restricted,
                hardwareId.c_str(), temp_metadata,
                device_models, temp_endpoint_id);

        delete[] device_models;
        delete[] temp_metadata;
        string ednpoint_str(temp_endpoint_id);
        delete[] temp_endpoint_id;
        checkResult(rv);

        return ednpoint_str;
    }

    const string GatewayDevice::MANUFACTURER("manufacturer");
    const string GatewayDevice::MODEL_NUMBER("modelNumber");
    const string GatewayDevice::SERIAL_NUMBER("serialNumber");
    const string GatewayDevice::DEVICE_CLASS("deviceClass");
    const string GatewayDevice::PROTOCOL("protocol");
    const string GatewayDevice::PROTOCOL_DEVICE_CLASS("protocolDeviceClass");
    const string GatewayDevice::PROTOCOL_DEVICE_ID("protocolDeviceId");
#endif
};