/* 
 * File:   HighwaysParser.h
 * 
 * The HighwaysParser class takes in a character buffer and parses it into a 
 * vector of FEP_LINEs and a vector of STATIONS. The buffer is sent in via the
 * constructor and the FEP_LINE and STATION vectors are accessible via public
 * members.
 * 
 * @author John A. Torres
 */

#include "HighwaysParser.h"

// The public stations member, containing the parsed vector of STATIONS
HighwaysParser::HighwaysParser(char * hwyData) {
    parseLines(hwyData);
}

// Frees all allocated memory in the class
HighwaysParser::~HighwaysParser() {
    // deallocate FEPLines
    for(int i = 0; i < this->lines.size(); i++)
    {
        delete this->lines.at(i);
    }
    // deallocate stations
    for(int i = 0; i < this->stations.size(); i++)
    {
        // deallocate loops
        for(int j = 0; j < this->stations.at(i)->loops.size(); j++)
        {
            // deallocate loop_loc
            delete this->stations.at(i)->loops.at(j)->loop_loc;
            // deallocate loop
            delete this->stations.at(i)->loops.at(j);
        }
        // deallocate station dataPack message
        delete this->stations.at(i)->dataPack;
        // deallocate station
        delete this->stations.at(i);
    }
}

/**
 * Parses the buffer into FEP_LINE and STATION vectors.
 * 
 * @param highwaysData buffer
 */
void HighwaysParser::parseLines(char * hwyData)
{
    // convert buffer to cpp string type
    string highwaysData = hwyData;
    // create buffer stream
    istringstream highwaysStream(highwaysData);
    // get the number of FEPLines
    string currLine;
    getline(highwaysStream, currLine);
    int numLines;
    sscanf(currLine.c_str(), "%d", &numLines);
    
    // declare variables used in parsing lines and stations
    int lineNum = 0;
    long lds = 0;
    long ldsIndex = 0;
    short count = 0;
    int schedule = 0;
    int lineInfo = 0;
    long systemKey = 0;
    long globalSeq = 0;
    long schedleSeq = 0;
    short dropNum = 0;
    int routeNum = 0;
    float postmile = 0;
    long loopID = 0;
    float occ = 0;
    int vol = 0;

    // for each line
    for(int lineIndex = 0; lineIndex < numLines; lineIndex++)
    {
        FEP_LINE * newLine = new FEP_LINE;
        
        getline(highwaysStream, currLine);
        int numStations = 0;
        sscanf(currLine.c_str(), "%d %hd %d", &lineNum, &count, &numStations);
        newLine->lineNum = lineNum;
        newLine->count = count;
        newLine->schedule = schedule;
        newLine->lineInfo = lineInfo;
        newLine->systemKey = systemKey;
        newLine->globalSeq = globalSeq;
        newLine->schedleSeq = schedleSeq;
        
        // for each station
        for(int stationIndex = 0; stationIndex < numStations; stationIndex++)
        {
            STATION * newStation = new STATION;
    
            int numLoops = 0;
            getline(highwaysStream, currLine);
            char direction;
            sscanf(currLine.c_str(), "%ld %hd %d %c %f %d", &lds, &dropNum, &routeNum, &direction,
                    &postmile, &numLoops);
            newLine->lds.push_back(lds);
            newLine->ldsIndex.push_back(ldsIndex++);
            newStation->lds = lds;
            newStation->line_num = lineNum;
            newStation->drop = dropNum;
            newStation->pos = 0;
            newStation->MlTotVol = 0;
            newStation->OppTotVol = 0;
            // for each loop
            for(int loopIndex = 0; loopIndex < numLoops; loopIndex++)
            {
                LOOP * newLoop = new LOOP;
                
                getline(highwaysStream, currLine);
                newLoop->loop_loc = (char *) malloc(25 * sizeof(char));
                sscanf(currLine.c_str(), "%ld %f %d %s", &loopID, &occ, &vol, newLoop->loop_loc);
                newLoop->loopID = loopID;
                newLoop->occ = occ;
                newLoop->vol = vol;
                newLoop->spd = 0;
                newStation->loops.push_back(newLoop);
            }
            newStation->length = newStation->loops.size() * 2 + CONTROL_DATA_LEN;
            newStation->dataPack = DataPacker::packData(newStation);
            
            // add new station to stations vector
            this->stations.push_back(newStation);
        }
        // add new line to lines vector
        this->lines.push_back(newLine);
    }
}