/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#include "ArtiSynthSimulator.h"

#include "SimulatorFactory.h"

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

using namespace std;

MML_DECL_CLASS(ArtisynthSimulator)

bool artisynthRegistered = SimulatorFactory::getInstance()->registerClass<ArtisynthSimulator>("artisynth", false);

// -------------------- constructor --------------------
ArtisynthSimulator::ArtisynthSimulator(MonitoringManager* monitoringManager): NonInteractiveSimulator(monitoringManager),
    artisynthPath{ARTISYNTH_BIN},
    workingDir{ARTISYNTH_WORKING_DIR} {
    if (workingDir[workingDir.length() - 1] != '/') {
        workingDir = workingDir + "/";
    }
}

// -------------------- constructor --------------------
ArtisynthSimulator::ArtisynthSimulator(MonitoringManager* monitoringManager, const char* file): NonInteractiveSimulator(monitoringManager, file) {
    //TODO
    std::cerr << "not possible yet for Artisynth" << std::endl;
}


// -------------------- destructor --------------------
ArtisynthSimulator::~ArtisynthSimulator() {
}

// -------------------- init --------------------
void ArtisynthSimulator::init() {
    //create working directory if [ -d "$dir" ]; then  fi
    string str = "mkdir -p " + workingDir;
    system(str.c_str());
}

// -------------------- end --------------------
void ArtisynthSimulator::end() {
    // delete temporary files
}

void ArtisynthSimulator::createPml(const char* inputFile, const char* pmlFile) {
    //TODO implement
    std::cerr << "not possible yet for Artisynth" << std::endl;
}


// -------------------- doCalc --------------------
bool ArtisynthSimulator::doCalc() {
    runArtisynth();
    return true;
}

// -------------------- runAnsys
void ArtisynthSimulator::runArtisynth() {
    //create .node and .elem file in the working directory
    std::string str;
    std::string fileName = "ArtisynthFile";
    str = workingDir + fileName;
    monitoringManager->getPml()->exportAnsysMesh(str);
    string s = artisynthPath + " -mml -elem " + str + ".elem -node " + str + ".node";
    system(s.c_str());

}
// -------------------- getPosition --------------------
void ArtisynthSimulator::getPosition(int index, double position[3]) {
    int step = monitoringManager->getCurrentStep();

    stringstream ss;
    string str;
    ss << step;
    ss >> str;
    str = workingDir + str + ".pos";
    ifstream fichier;
    fichier.open(str.c_str(), ios::in);
    int i;
    double x;
    double y;
    double z;
    while (!fichier.eof()) {
        fichier >> i;
        fichier >> x;
        fichier >> y;
        fichier >> z;
        // NOTE Ansys node index starts at 1 not 0 (fortran heritage!)
        if (i - 1 == index) {
            position[0] = x;
            position[1] = y;
            position[2] = z;
            break;
        }
    }
    fichier.close();
}

// -------------------- getPosition --------------------
void ArtisynthSimulator::getForce(int index, double force[3]) {
    //TODO (should return booleen when non implemented?)
}


// -------------------- getMaxStep --------------------
int ArtisynthSimulator::getMaxStep() {
    ifstream fichier;
    string str = workingDir + "max.tmp";
    fichier.open(str.c_str(), ios::in);
    int i;
    fichier >> i;
    return i;
    fichier.close();
}

// -------------------- getTime --------------------
double ArtisynthSimulator::getTime(int step) {
    ifstream fichier;
    string str = workingDir + "times.tmp";
    fichier.open(str.c_str(), ios::in);
    double i;
    for (int j = 1; j <= step; j++) {
        fichier >> i;
    }
    return i;
    fichier.close();
}
