
#include "ImportMarc.h"
#include "RTMSimulator.h"
#include "Import.h"

#include <QApplication>
#include <QDesktopWidget>
#include <QString>
#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>
#include <QFile>
#include <QStringList>
#include <QTextStream>

#include <cmath>
#include <iostream>
#include <list>

/**
 * Creates a temporary import object to read in a Marc Mentat file.
 * @param pFile File to read in.
 * @param pSimulator Pointer to the RTMSimulator object to read into.
 */
ImportMarc::ImportMarc(QFile* pFile, RTMSimulator* pSimulator):
        ImportFormat(pSimulator),
        m_numberOfNodes(0),
        m_numberOfElements(0)
{
    read(pFile);
}

/**
 * Creates a temporary import object to read in a Marc Mentat file.
 * @param strFile Fully qualified path file to read in.
 * @param pSimulator Pointer to the RTMSimulator object to read into.
 */
ImportMarc::ImportMarc(QString strFile, RTMSimulator* pSimulator):
        ImportFormat(pSimulator),
        m_numberOfNodes(0),
        m_numberOfElements(0)
{
    QFile* pFile = new QFile(strFile);
    read(pFile);
    pFile->close();
}

/**
 * Reads in the information from a Marc Mentat file
 * @param pFile Pointer to the file to read from.
 */
void ImportMarc::read(QFile* pFile)
{
    InfoBox infoBox("reading Size Information...");
    qApp->processEvents();
    if(!readSizeInformation(pFile))
    {
        //here we should display an error message
        infoBox.hide();
        return;
    }

    infoBox.setText("importing Nodes...");
    qApp->processEvents();
    if(!importNodes(pFile))
    {
        //here we should display an error message
        infoBox.hide();
        return;
    }

    infoBox.setText("importing Connections...");
    qApp->processEvents();
    if(!importConnections(pFile))
    {
        //here we should display an error message
        infoBox.hide();
        return;
    }
    infoBox.hide();
}

/**
 * Reads the size information from a Marc Mentat file. (number of elements, number of nodes)
 * @param pFile Pointer to the file to read from.
 */
bool ImportMarc::readSizeInformation(QFile* pFile)
{
    while (!pFile->atEnd())
    {
        QString line = pFile->readLine();
        if(line.contains("sizing",Qt::CaseInsensitive))
        {
            QStringList lineContents = line.split(QRegExp("\\s+"),QString::SkipEmptyParts);
            m_numberOfElements = lineContents[2].toInt();
            m_numberOfNodes = lineContents[3].toInt();
            break;
        }
    }
    pFile->reset();
    return true;
}

/**
 * Imports node information from a Marc Mentat file.
 * @param pFile Pointer to the file to read from.
 */
bool ImportMarc::importNodes(QFile* pFile)
{
    QString line;
    while (!pFile->atEnd())
    {
        line = pFile->readLine();
        if(line.contains("coordinates",Qt::CaseInsensitive))
        {
            line = pFile->readLine(); //read another line, because first line after coordinates is not interresting
            break;
        }
    }

    for(int i=0; i<m_numberOfNodes && !pFile->atEnd(); i++)
    {
        line = pFile->readLine();
        if(!line.at(0).isSpace())
        {
            //display error: import file corrupt
            break;
        }
        int nodeId;
        double x;
        int x_exp;
        double y;
        int y_exp;
        double z;
        int z_exp;

        QTextStream istream(&line);
        istream >> nodeId >> x >> x_exp >> y >> y_exp >> z >> z_exp;
        x = x*pow((double)10,x_exp);
        y = y*pow((double)10,y_exp);
        z = z*pow((double)10,z_exp);

        m_pSimulator->addNode(nodeId,x,y,z);
    }

    pFile->reset();
    return true;
}

/**
 * Imports all the connection information from a Marc Mentat file.
 * @param pFile Pointer to the file to read from.
 */
bool ImportMarc::importConnections(QFile* pFile)
{
    QString line;
    while (!pFile->atEnd())
    {
        line = pFile->readLine();
        if(line.contains("connectivity",Qt::CaseInsensitive))
        {
            line = pFile->readLine(); //read another line, because first line after connectivity is not interresting
            break;
        }
    }

    for(int i=0; i<m_numberOfElements && !pFile->atEnd(); i++)
    {
        line = pFile->readLine().trimmed();
        QTextStream istream(&line);

        int connectivityId, unknown, connection;
        std::list<int> connectionList;
        istream >> connectivityId >> unknown;
        while(!istream.atEnd())
        {
            istream >> connection;
            connectionList.push_back(connection);
        }

        if(connectionList.size() >= 2)
        {
            for(std::list<int>::const_iterator it = connectionList.begin(); it != connectionList.end(); it++)
            {
                std::list<int>::const_iterator itNode2 = it;
                itNode2++;
                if(itNode2 == connectionList.end())
                    itNode2 = connectionList.begin();

                m_pSimulator->setDirectNeighbor(*it,*itNode2);
                m_pSimulator->setDirectNeighbor(*itNode2,*it);
            }
            addShapePart(&connectionList);
        }
    }

    pFile->reset();
    return true;
}


