/*
 * Inscoper NBO Example: Inline Elements
 * =====================================
 * This example demonstrates how to work with inline element types, which the
 * generator creates for elements declared directly inside their parent rather
 * than as a named schema type.
 *
 * Prerequisites:
 * -------------
 * 1. Installation: the include directory of the release must be on the include
 *    paths, and the application must link against the NBO library.
 */

// --8<-- [start:main_logic]
#include <NBO/NBO/PlateID_Type.h>
#include <NBO/NBO/Screen.h>
#include <NBO/NBO/ScreenID_Type.h>

#include <iostream>
#include <memory>

using namespace Inscoper;

int main() {
    // Step 1: Recognize an inline type by its name
    // An element declared inside Screen produces the nested class
    // Screen::Inline<ElementName>, which exists only in the context of that parent.
    NBO::Screen screen;

    NBO::ScreenID_TypePtr screenId = std::make_shared<NBO::ScreenID_Type>();
    screenId->set("Screen:1");
    screen.setID(screenId);

    NBO::Screen::InlineDescriptionPtr description =
        std::make_shared<NBO::Screen::InlineDescription>();
    description->set("Plate screen, 3 plates");
    screen.setDescription(description);

    // Step 2: Repeated inline elements behave like any other list
    for (const std::string &plate : {"Plate:1", "Plate:2"}) {
        NBO::Screen::InlinePlateRefPtr plateRef = std::make_shared<NBO::Screen::InlinePlateRef>();
        NBO::PlateID_TypePtr plateId = std::make_shared<NBO::PlateID_Type>();
        plateId->set(plate);
        plateRef->setID(plateId);
        screen.addToPlateRef_List(plateRef);
    }

    std::cout << screen.toXmlString() << std::endl;

    // Step 3: Inline elements are read back from XML into the same classes
    screen.fromXmlString(R"(<?xml version="1.0"?>
<Screen ID="Screen:03">
  <Description>Rewritten from XML</Description>
  <PlateRef ID="Plate:01" />
  <PlateRef ID="Plate:02" />
  <PlateRef ID="Plate:03" />
</Screen>)");

    std::cout << screen.getDescription()->get() << std::endl;
    for (const auto &plateRef : screen.getPlateRef_List()) {
        std::cout << plateRef->getID()->get() << " ";
    }
    std::cout << std::endl;

    return 0;
}
// --8<-- [end:main_logic]
