function rrApp = startRoadRunnerForScenario(scenario,options)
%STARTROADRUNNERFORSCENARIO Starts RoadRunner for a drivingScenario object
%   rrApp = startRoadRunnerForScenario(scenario) starts RoadRunner for a driving
%   scenario object, scenario. This is accomplished by exporting RoadRunner
%   HD Map and CSV Trajectory files from the driving scenario and importing
%   them into RoadRunner. The returned rrApp object provides methods for
%   performing common workflow tasks such as opening, closing, and saving
%   scenes and projects and importing data from file and exporting scenes
%   in RoadRunner.
%
%   startRoadRunnerForScenario(scenario,Name=Value) specifies additional
%   name-value arguments.
%
%   startRoadRunnerForScenario arguments:
%
%   FileName            File name that will be used when exporting the
%                       RoadRunner HD Map and CSV Trajectory files for
%                       actors. Default: "untitled".
%
%   Asset path of each actor in the driving scenario is specified using the
%   actor property "AssetPath". If AssetPath of an actor is empty string,
%   ClassID of the actor is used to determine the RoadRunner asset path.
%   Default mapping of driving scenario actor ClassID and a RoadRunner
%   asset path is defined using a MATLAB settings API. Run: s = settings;
%   s.drivingscenario.actors.DefaultClassIDToAssetPathMapping to customize
%   the personal or temporary values for it.
%
%   Run this function from a folder that has write permission as files
%   will be generated in the current folder.
%
%   See also drivingScenario, drivingScenario/actor, settings.

%   Copyright 2023 The MathWorks, Inc.

arguments
    scenario (1,1) drivingScenario
    options.FileName string = "untitled"
end
if ~isa(scenario.Scene,'driving.scene.TileBasedScene')
    error(message('driving:scenario:FeatureNotSupported',mfilename));
end
if isempty(scenario.RoadTiles)
    error(message('driving:scenario:OSCEmptyScenario'));
end
fileName = options.FileName;
try
    % Starting RoadRunner
    rrApp = [];
    s = settings;
    customInstallPath = char(s.roadrunner.application.InstallationFolder.ActiveValue);
    projectFolder = char(s.roadrunner.application.ProjectFolder.ActiveValue);
    if isempty(customInstallPath) || isempty(projectFolder)
        rrApp = roadrunnerSetup;
        if isempty(rrApp)
            return;
        end
    end
    [~, fileName] = fileparts(char(fileName));
    csvFilename = fileName;
    fileName = fileName + ".rrhd";
    % Export file if we can try to start RoadRunner
    export(scenario,"RoadRunner HD Map",fileName);
    if isempty(rrApp)
        rrApp = roadrunner;
    end
    % Set the RoadRunner scenes world origin
    geoRef = scenario.GeoReference;
    if isempty(geoRef)
        geoRef = driving.internal.MapUtils.DefaultGeoReference;
    end
    changeWorldSettings(rrApp,WorldOrigin=geoRef(1:2));
    % Importing the RoadRunner HD Map File (scene elements)
    impOpts = roadrunnerHDMapImportOptions("BuildOptions",roadrunnerHDMapBuildOptions(...
        EnableOverlapGroupsOptions=enableOverlapGroupsOptions(IsEnabled=false)));
    importScene(rrApp,fullfile(pwd,fileName),"RoadRunner HD Map",impOpts);
    % If there are actors with trajectories, attempt creating a
    % RoadRunner Scenario and importing them.
    sdb = driving.internal.scenarioApp.ScenarioDataBuilder;
    sdb.Scenario = scenario;
    [numMovableActors,aPoses,aInfo,foundReverse] = roadrunnerCSVActorPoses(sdb);
    if numMovableActors > 0
        newScenario(rrApp);
    end
    if foundReverse
        % Show an error that scenarios with reverse
        % motion is not supported.
        throw(MException("driving:scenarioApp:ReverseMotionNotSupported",...
            getString(message('driving:scenarioApp:ReverseMotionNotSupported'))));
    end
    for andx = 1:numMovableActors
        % Filename for each actor
        filenameEachActor = csvFilename + "_"  + aInfo(andx).Name + ".csv";
        % Table for CSV data of each actor
        CSVData = table(aPoses(andx).Time, aPoses(andx).X,aPoses(andx).Y, ...
            aPoses(andx).Z,aPoses(andx).Yaw,aPoses(andx).Pitch,aPoses(andx).Roll);
        CSVData.Properties.VariableNames = ["time","x","y","z","yaw","pitch","roll"];
        % Save the CSV file
        writetable(CSVData,filenameEachActor);
        % Import into RoadRunner
        aImpOptions = actorImportOptions(Name=aInfo(andx).Name,...
            ID=aInfo(andx).ID,Color=aInfo(andx).Color,...
            AssetPath=aInfo(andx).AssetPath);
        impOpts = csvTrajectoryImportOptions(ActorImportOptions=aImpOptions);
        if aInfo(andx).SpawnTime ~= 0
            impOpts.SpawnTime = aInfo(andx).SpawnTime;
        end
        if ~isinf(aInfo(andx).RemoveTime)
            impOpts.RemoveTime = aInfo(andx).RemoveTime;
        end
        importScenario(rrApp, fullfile(pwd,filenameEachActor), "CSV Trajectory", impOpts);
    end
catch E
    throwAsCaller(E);
end
end