/*
 * Inscoper NBO Example: Import a MicroMetaApp Configuration
 * ========================================================
 * This example demonstrates how to populate an NBO Instrument from a MicroMetaApp
 * JSON configuration and export it as NBO-XML.
 *
 * Prerequisites:
 * -------------
 * 1. Installation: the include directory of the release must be on the include
 *    paths, and the application must link against the NBO library.
 * 2. Sample Data: this example reads micrometaapp_nikon_ti2.json. Change
 *    MMA_JSON_PATH below to the location where you saved it, or to your own
 *    MicroMetaApp configuration.
 */

#include <NBO/NBO/Instrument.h>
#include <NBO/Shared/Exception/InscoperNBOException.h>

#include <filesystem>
#include <iostream>
#include <string>

using namespace Inscoper;

// --8<-- [start:main_logic]
const std::string MMA_JSON_PATH = "micrometaapp_nikon_ti2.json";

int main() {
    // Step 1: Import the configuration
    // fromMicroMetaAppJsonFile() parses the JSON produced by MicroMetaApp, maps every
    // component to its NBO counterpart, and fills the instrument in a single call.
    NBO::Instrument instrument;
    instrument.fromMicroMetaAppJsonFile(MMA_JSON_PATH);

    // A missing or unreadable file throws InscoperNBOException
    try {
        NBO::Instrument missing;
        missing.fromMicroMetaAppJsonFile("does_not_exist.json");
    } catch (const NBO::InscoperNBOException &error) {
        std::cout << "Import failed: " << error.what() << std::endl;
    }

    // Step 2: Inspect what the import produced
    std::cout << "Instrument: " << instrument.getID()->get() << std::endl;

    for (const auto &stand : instrument.getMicroscopeStandGroup_List()) {
        std::cout << "Stand: " << stand->getXMLName() << " " << stand->getManufacturer() << " "
                  << stand->getModel() << std::endl;
    }

    for (const auto &objective : instrument.getObjective_List()) {
        std::cout << "Objective: " << objective->getModel() << " - "
                  << objective->getMagnification() << "x" << std::endl;
    }

    for (const auto &detector : instrument.getDetectorGroup_List()) {
        std::cout << "Detector: " << detector->getXMLName() << " " << detector->getModel()
                  << std::endl;
    }

    for (const auto &lightSource : instrument.getLightSourceGroup_List()) {
        std::cout << "Light source: " << lightSource->getXMLName() << " "
                  << lightSource->getModel() << std::endl;
    }

    // Step 3: Export the imported instrument as NBO-XML
    // Pass false to write exactly what the import produced, without validating the
    // document and without filling in schema default values.
    std::filesystem::path outputPath =
        std::filesystem::temp_directory_path() / "instrument_from_mma.xml";
    instrument.toXmlFile(outputPath.string(), false);
    std::cout << "NBO-XML written to " << outputPath.string() << std::endl;

    return 0;
}
// --8<-- [end:main_logic]
