/*
 * Copyright (c) 2007 INRIA
 *               2009,2010 Contributors
 *
 * SPDX-License-Identifier: GPL-2.0-only
 *
 * Author: Martín Giachino <martin.giachino@gmail.com>
 *
 *
 * This example demonstrates the use of Ns2MobilityHelper class to work with mobility.
 *
 * Detailed example description.
 *
 *  - intended usage: this should be used in order to load ns2 movement trace files into ns3.
 *  - behavior:
 *      - Ns2MobilityHelper object is created, associated to the specified trace file.
 *      - A log file is created, using the log file name argument.
 *      - A node container is created with the number of nodes specified in the command line.  For
 * the default ns-2 trace, specify the value 2 for this argument.
 *      - the program calls the Install() method of Ns2MobilityHelper to set mobility to nodes. At
 * this moment, the file is read line by line, and the movement is scheduled in the simulator.
 *      - A callback is configured, so each time a node changes its course a log message is printed.
 *  - expected output: example prints out messages generated by each read line from the ns2 movement
 * trace file. For each line, it shows if the line is correct, or of it has errors and in this case
 * it will be ignored.
 *
 * Usage of ns2-mobility-trace:
 *
 *  ./ns3 run "ns2-mobility-trace \
 *        --traceFile=src/mobility/examples/default.ns_movements
 *        --nodeNum=2  --duration=100.0 --logFile=ns2-mobility-trace.log"
 *
 *  NOTE: ns2-traces-file could be an absolute or relative path. You could use the file
 * default.ns_movements included in the same directory as the example file. NOTE 2: Number of nodes
 * present in the trace file must match with the command line argument. Note that you must know it
 * before to be able to load it. NOTE 3: Duration must be a positive number and should match the
 * trace file. Note that you must know it before to be able to load it.
 */

#include "ns3/core-module.h"
#include "ns3/mobility-module.h"
#include "ns3/ns2-mobility-helper.h"

#include <fstream>
#include <iostream>
#include <sstream>

using namespace ns3;

// Prints actual position and velocity when a course change event occurs
static void
CourseChange(std::ostream* os, std::string foo, Ptr<const MobilityModel> mobility)
{
    Vector pos = mobility->GetPosition(); // Get position
    Vector vel = mobility->GetVelocity(); // Get velocity

    // Prints position and velocities
    *os << Simulator::Now() << " POS: x=" << pos.x << ", y=" << pos.y << ", z=" << pos.z
        << "; VEL:" << vel.x << ", y=" << vel.y << ", z=" << vel.z << std::endl;
}

// Example to use ns2 traces file in ns3
int
main(int argc, char* argv[])
{
    std::string traceFile;
    std::string logFile;

    int nodeNum;
    double duration;

    // Enable logging from the ns2 helper
    LogComponentEnable("Ns2MobilityHelper", LOG_LEVEL_DEBUG);

    // Parse command line attribute
    CommandLine cmd(__FILE__);
    cmd.AddValue("traceFile", "Ns2 movement trace file", traceFile);
    cmd.AddValue("nodeNum", "Number of nodes", nodeNum);
    cmd.AddValue("duration", "Duration of Simulation", duration);
    cmd.AddValue("logFile", "Log file", logFile);
    cmd.Parse(argc, argv);

    // Check command line arguments
    if (traceFile.empty() || nodeNum <= 0 || duration <= 0 || logFile.empty())
    {
        std::cout << "Usage of " << argv[0]
                  << " :\n\n"
                     "./ns3 run \"ns2-mobility-trace"
                     " --traceFile=src/mobility/examples/default.ns_movements"
                     " --nodeNum=2 --duration=100.0 --logFile=ns2-mob.log\" \n\n"
                     "NOTE: ns2-traces-file could be an absolute or relative path. You could use "
                     "the file default.ns_movements\n"
                     "      included in the same directory of this example file.\n\n"
                     "NOTE 2: Number of nodes present in the trace file must match with the "
                     "command line argument and must\n"
                     "        be a positive number. Note that you must know it before to be able "
                     "to load it.\n\n"
                     "NOTE 3: Duration must be a positive number. Note that you must know it "
                     "before to be able to load it.\n\n";

        return 0;
    }

    // Create Ns2MobilityHelper with the specified trace log file as parameter
    Ns2MobilityHelper ns2 = Ns2MobilityHelper(traceFile);

    // open log file for output
    std::ofstream os;
    os.open(logFile);

    // Create all nodes.
    NodeContainer stas;
    stas.Create(nodeNum);

    ns2.Install(); // configure movements for each node, while reading trace file

    // Configure callback for logging
    Config::Connect("/NodeList/*/$ns3::MobilityModel/CourseChange",
                    MakeBoundCallback(&CourseChange, &os));

    Simulator::Stop(Seconds(duration));
    Simulator::Run();
    Simulator::Destroy();

    os.close(); // close log file
    return 0;
}
