void SimulatorRemoteResourceImpl::configure(const std::string &path)
{
    if (path.empty())
    {
        OC_LOG(ERROR, TAG, "Invalid path given for configuration !");
        throw InvalidArgsException(SIMULATOR_INVALID_PARAM, "Empty path string!");
    }

    std::shared_ptr<RAML::RamlParser> ramlParser = std::make_shared<RAML::RamlParser>(path);
    RAML::RamlPtr raml = ramlParser->getRamlPtr();

    configure(raml);
}
void SimulatorRemoteResourceImpl::stopVerification(int id)
{
    if (id < 0)
    {
        OC_LOG(ERROR, TAG, "Invalid session id!");
        throw InvalidArgsException(SIMULATOR_INVALID_PARAM, "Invalid ID!");
    }

    if (!m_autoRequestGenMngr)
    {
        OC_LOG(ERROR, TAG, "Invalid auto request generation manager !");
        throw NoSupportException("Resource is not configured with RAML!");
    }

    m_autoRequestGenMngr->stop(id);
}
void SimulatorRemoteResourceImpl::observe(ObserveType type,
        ObserveNotificationCallback callback)
{
    if (!callback)
    {
        OC_LOG(ERROR, TAG, "Invalid callback!");
        throw InvalidArgsException(SIMULATOR_INVALID_CALLBACK, "Invalid callback!");
    }

    std::lock_guard<std::mutex> lock(m_observeMutex);
    if (m_observeState)
    {
        OC_LOG(WARNING, TAG, "Resource already in observe state !");
        throw SimulatorException(SIMULATOR_ERROR, "Resource is already being observed!");
    }

    OC::ObserveCallback observeCallback = [this, callback](const OC::HeaderOptions & headerOptions,
                                          const OC::OCRepresentation & rep, const int errorCode,
                                          const int sequenceNum)
    {
        // Convert OCRepresentation to SimulatorResourceModel
        SimulatorResourceModelSP repModel = SimulatorResourceModel::create(rep);
        callback(m_id, static_cast<SimulatorResult>(errorCode), repModel, sequenceNum);
    };

    OC::ObserveType observeType = OC::ObserveType::Observe;
    if (type == ObserveType::OBSERVE_ALL)
    {
        observeType = OC::ObserveType::ObserveAll;
    }

    try
    {
        OCStackResult ocResult = m_ocResource->observe(observeType, OC::QueryParamsMap(), observeCallback);
        if (OC_STACK_OK != ocResult)
        {
            throw SimulatorException(static_cast<SimulatorResult>(ocResult), OC::OCException::reason(ocResult));
        }
    }
    catch (OC::OCException &e)
    {
        throw SimulatorException(static_cast<SimulatorResult>(e.code()), e.reason());
    }

    m_observeState = true;
}
void SimulatorRemoteResourceImpl::get(const std::map<std::string, std::string> &queryParams,
                                      ResponseCallback callback)
{
    if (!callback)
    {
        OC_LOG(ERROR, TAG, "Invalid callback!");
        throw InvalidArgsException(SIMULATOR_INVALID_CALLBACK, "Invalid callback!");
    }

    if (!m_getRequestSender)
    {
        OC_LOG(ERROR, TAG, "Invalid GET request sender !");
        throw NoSupportException("Can not send GET request on this resource!");
    }

    m_getRequestSender->sendRequest(std::string(), queryParams,
                                    nullptr, std::bind(
                                        &SimulatorRemoteResourceImpl::onResponseReceived,
                                        this, std::placeholders::_1, std::placeholders::_2, callback));
}
void SimulatorRemoteResourceImpl::post(const std::string &interfaceType,
                                       const std::map<std::string, std::string> &queryParams,
                                       SimulatorResourceModelSP representation,
                                       ResponseCallback callback)
{
    if (!callback)
    {
        OC_LOG(ERROR, TAG, "Invalid callback!");
        throw InvalidArgsException(SIMULATOR_INVALID_CALLBACK, "Invalid callback!");
    }

    if (!m_postRequestSender)
    {
        OC_LOG(ERROR, TAG, "Invalid POST request sender !");
        throw NoSupportException("Can not send POST request on this resource!");
    }

    m_postRequestSender->sendRequest(interfaceType, queryParams,
                                     representation, std::bind(
                                         &SimulatorRemoteResourceImpl::onResponseReceived,
                                         this, std::placeholders::_1, std::placeholders::_2, callback));
}
int SimulatorRemoteResourceImpl::startVerification(RequestType type,
        StateCallback callback)
{
    if (!callback)
    {
        OC_LOG(ERROR, TAG, "Invalid callback!");
        throw InvalidArgsException(SIMULATOR_INVALID_CALLBACK, "Invalid callback!");
    }

    if (!m_autoRequestGenMngr)
    {
        OC_LOG(ERROR, TAG, "Invalid auto request generation manager !");
        throw NoSupportException("Resource is not configured with RAML!");
    }

    if (m_requestModelList.end() == m_requestModelList.find(type))
        throw NoSupportException("Resource does not support this request type!");

    // Local callback for handling progress sate callback
    AutoRequestGeneration::ProgressStateCallback localCallback = [this, callback](
                int sessionId, OperationState state)
    {
        callback(m_id, sessionId, state);
    };

    switch (type)
    {
    case RequestType::RQ_TYPE_GET:
        if (m_getRequestSender)
        {
            return m_autoRequestGenMngr->startOnGET(m_getRequestSender,
                                                    m_requestModelList[RequestType::RQ_TYPE_GET]->getQueryParams(),
                                                    localCallback);
        }
        break;

    case RequestType::RQ_TYPE_PUT:
        if (m_putRequestSender)
        {
            return m_autoRequestGenMngr->startOnPUT(m_putRequestSender,
                                                    m_requestModelList[RequestType::RQ_TYPE_PUT]->getQueryParams(),
                                                    m_requestModelList[RequestType::RQ_TYPE_PUT]->getRepSchema(),
                                                    localCallback);
        }
        break;

    case RequestType::RQ_TYPE_POST:
        if (m_postRequestSender)
        {
            return m_autoRequestGenMngr->startOnPOST(m_putRequestSender,
                    m_requestModelList[RequestType::RQ_TYPE_POST]->getQueryParams(),
                    m_requestModelList[RequestType::RQ_TYPE_POST]->getRepSchema(),
                    localCallback);
        }
        break;

    case RequestType::RQ_TYPE_DELETE:
    default:
        throw NoSupportException("Resource does not support this request type!");
    }

    return -1; // Code should not reach here
}
void MatrixMulArgsParser::parse(int argc, char *argv[]) {
    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];
        if ((arg == "-h") || (arg == "--help")) {
            showUsage(argv[0]);
            return;
        }
        else if ((arg == "-l") || (arg == "--left")) {
            if (i + 1 < argc) { // Make sure we aren't at the end of argv!
                args[MATRIX_LEFT] = argv[++i]; // Increment 'i' so we don't get the argument as the next argv[i].
            }
            else { // Uh-oh, there was no argument to the destination option.
                std::cerr << "--left option requires one argument. See --help for more info." << std::endl;
                throw InvalidArgsException();
            }
        }
        else if ((arg == "-r") || (arg == "--right")) {
            if (i + 1 < argc) { // Make sure we aren't at the end of argv!
                args[MATRIX_RIGHT] = argv[++i]; // Increment 'i' so we don't get the argument as the next argv[i].
            }
            else { // Uh-oh, there was no argument to the destination option.
                std::cerr << "--right option requires one argument. See --help for more info." << std::endl;
                throw InvalidArgsException();
            }
        }

        else if ((arg == "-o") || (arg == "--output")) {
            if (i + 1 < argc) { // Make sure we aren't at the end of argv!
                args[OUTPUT] = argv[++i]; // Increment 'i' so we don't get the argument as the next argv[i].
            }
            else { // Uh-oh, there was no argument to the destination option.
                std::cerr << "--output option requires one argument. See --help for more info." << std::endl;
                throw InvalidArgsException();
            }
        }
        else if ((arg == "-s") || (arg == "--size")) {
            if (i + 1 < argc) { // Make sure we aren't at the end of argv!
                if (!isInt(argv[i + 1])) {
                    std::cerr << "--size must be a positive number. See --help for more info." << std::endl;
                    throw InvalidArgsException();
                }
                if (!isPowerOf2(std::stoi(argv[i + 1]))) {
                    std::cerr << "--size must be a power of 2. See --help for more info." << std::endl;
                    throw InvalidArgsException();
                }
                args[MATRIX_SIZE] = argv[++i]; // Increment 'i' so we don't get the argument as the next argv[i].
            }
            else { // Uh-oh, there was no argument to the destination option.
                std::cerr << "--size option requires one argument. See --help for more info." << std::endl;
                throw InvalidArgsException();
            }
        }
        else if ((arg == "-a") || (arg == "--algorithm")) {
            if (i + 1 < argc) { // Make sure we aren't at the end of argv!
                if (!isInt(argv[i + 1])) {
                    std::cerr << "--algorithm option can contain only specific values. See --help for more info." << std::endl;
                    throw InvalidArgsException();
                }
                if (std::stoi(argv[i + 1]) < 1 || std::stoi(argv[i + 1]) > 2) {
                    std::cerr << "--algorithm option can contain only specific values. See --help for more info." << std::endl;
                    throw InvalidArgsException();
                }
                args[ALGORITHM] = argv[++i]; // Increment 'i' so we don't get the argument as the next argv[i].
            }
            else { // Uh-oh, there was no argument to the destination option.
                std::cerr << "--size option requires one argument. See --help for more info. " << std::endl;
                throw InvalidArgsException();
            }
        }

        else if ((arg == "-rn") || (arg == "--random")) {
            args[RANDOM] = "true";
        }

        else {
            std::cerr << "Invalid arguments. See --help for more info." << std::endl;
            throw InvalidArgsException();
        }
    }

    if (args.find(MATRIX_SIZE) == args.end()) {
        std::cerr << "--size option is [REQUIRED]. See --help for more info." << std::endl;
        throw InvalidArgsException();
    }
    if (args.find(RANDOM) == args.end() &&
        (args.find(MATRIX_LEFT) == args.end() || args.find(MATRIX_RIGHT) == args.end())) {
        std::cerr << "If --random option is not specified --left and --right options are [REQUIRED]. See --help for more info." << std::endl;
        throw InvalidArgsException();
    }

}