
#include "ImportAnsys.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 <QRegExp>

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

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

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

/**
 * Reads in data from a Ansys file.
 * @param pFile File to read from
 */
void ImportAnsys::read(QFile* pFile)
{
    InfoBox infoBox("reading Size Information...");
    qApp->processEvents();

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

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

    infoBox.hide();
}

/**
 * Imports node information from a Ansys file.
 * @param pFile File to read from
 */
bool ImportAnsys::importNodes(QFile* pFile)
{
    QString line;
    while (!pFile->atEnd())
    {
        line = pFile->readLine();
        if(line.startsWith("nblock",Qt::CaseInsensitive))
        {
            pFile->readLine(); //read an empty line
            line = pFile->readLine();
            while(!line.contains(QRegExp("[a-z]|[A-D]|[F-Z]")))
            {
                if(line.at(0).isSpace())
                {
                    int nodeId = 0;
                    line.replace('-'," -");
                    line.replace("E -","E-");

                    QStringList tokens = line.split(QRegExp("[^\\d.+-E]"), QString::SkipEmptyParts); // \D = non digit

                    std::vector<double> coords;
                    int pos = 0;
                    for(QStringList::iterator it = tokens.begin(); it != tokens.end(); it++)
                    {
                        bool ok;
                        QString token = (*it);

                        switch(pos){
                                                case 0:
                            nodeId = token.toInt(&ok);
                            if(!ok)
                                return false;
                            break;
                                                case 3:
                                                case 4:
                                                case 5:
                            double coord = token.toDouble(&ok);
                            if(!ok)
                                return false;
                            else
                            {
                                coords.push_back(coord);
                            }
                            break;
                        }
                        pos++;
                    }

                    if(coords.size() >= 1)
                    {
                        while(coords.size() < 3)
                        {
                            coords.push_back(0);
                        }
                        m_pSimulator->addNode(nodeId,coords[0],coords[1],coords[2]);
                    }
                }
                line = pFile->readLine();
            }
        }
    }

    pFile->reset();
    return true;
}

/**
 * Importing connection information from an Ansys file.
 * @param pFile File to read from
 */
bool ImportAnsys::importConnections(QFile* pFile)
{
    QString line;
    while (!pFile->atEnd())
    {
        line = pFile->readLine();
        if(line.startsWith("eblock,19",Qt::CaseInsensitive))
        {
            pFile->readLine(); //read an empty line
            line = pFile->readLine();
            while(!line.contains(QRegExp("[a-z]|[A-Z]")))
            {
                if(line.at(0).isSpace())
                {
                    line = line.trimmed();
                    QTextStream istream(&line);

                    int connectivityId, unknown, connection;
                    int numOfVertices; // tripple or quad
                    std::list<int> connectionList;
                    istream			>> unknown >> unknown
                            >> unknown >> unknown
                            >> unknown >> unknown
                            >> unknown >> unknown //8 unknown parameters in the file
                            >> numOfVertices
                            >> unknown
                            >> connectivityId;
                    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);
                    }
                }
                line = pFile->readLine();
            }
        }
    }

    pFile->reset();
    return true;
}


