// $Id: SpaceConverter.cpp,v 1.14 2018/01/03 21:32:57 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Patrick Colacurcio, Peter Beerli, Mary Kuhner, Jon Yamato 
/* Authors: Patrick Colacurcio, Peter Beerli, Mary Kuhner, Jon Yamato 
and Joseph Felsenstein */


#include <vector>
#include <iostream>
#include <sstream>

#include "Converter_SpaceConverter.h"
#include "Converter_DataSourceException.h"
#include "Converter_LamarcDS.h"
#include "stringx.h"

//----------------------------------------------------------------------

SpaceConverter::SpaceConverter(LamarcDS& lamarc) :
    ConverterIf(), m_lamarc(lamarc)
{
} // SpaceConverter::ctor

//----------------------------------------------------------------------

SpaceConverter::~SpaceConverter()
{
} // SpaceConverter::dtor

//----------------------------------------------------------------------

void SpaceConverter::ValidateSpaceInfo(const SpaceMap& spaces,
                                       const string& fname) const
{
    // now make sure that every region that is addressed in the space info
    // exists in the data under the same name
    SpaceMap::const_iterator spaceit;
    for(spaceit = spaces.begin(); spaceit != spaces.end(); ++spaceit)
    {
        if (!m_lamarc.doesRegionNameExist(spaceit->first))
        {
            string errormsg = "Region name " + spaceit->first;
            errormsg += " was mentioned in file " + fname;
            errormsg += "\nbut no corresponding region name was found in the data.\n";
            errormsg += "Make sure that region names are used";
            errormsg += " consistently in all parts of data entry.";
            throw FileFormatError(errormsg);
        }
    }

} // SpaceConverter::ValidateSpaceInfo

//----------------------------------------------------------------------

SpaceMap SpaceConverter::ReadSpacingInfo(const string& filename) const
{
    SpaceMap spacings;

    ifstream spacefile(filename.c_str(),ios::in);

    if (!spacefile)
    {
        string errormsg = "I could not find file, " + filename;
        throw FileFormatError(errormsg);
    }

    string line, somestring;
    if (!getLine(spacefile,line))
    {
        string errormsg = "Your file, " + filename + ", appears";
        errormsg += " to be empty.";
        throw FileFormatError (errormsg);
    }

    bool notdone = true;
    bool firsttime  = true;
    long linenumber = 1;
    string regionname;
    vector<long> positions;

    // now parse the file line by line
    while(notdone)
    {
        istringstream linestream(line);

        skipWhiteSpace(linestream);
        somestring.erase();

        // process the first token in the line.
        if (getName(linestream,somestring))
        {
            if (!firsttime)  // insert previous finished region
                spacings.insert(make_pair(regionname,positions));
            firsttime = false;
            regionname = somestring;
            positions.clear();
        }
        else
        {
            if (IsInteger(somestring))
            {
                long position = FlagCheck(somestring,
                                          string("position number"));
                positions.push_back(position);
            }
            else
            {
                string errormsg = "An illegal region name was found";
                errormsg += " on line " + ToString(linenumber);
                errormsg += " of file " + filename +"\nTo be legal";
                errormsg += " a region name must have at least one";
                errormsg += " alphabetic character in it.";
                throw FileFormatError (errormsg);
            }
        }

        // process the rest of the line, which must be numbers
        skipWhiteSpace(linestream);
        while (linestream.good())
        {
            somestring.erase();
            if (getNumber(linestream,somestring))
            {
                long position = FlagCheck(somestring,
                                          string("position number"));
                positions.push_back(position);
            }
            else
            {
                string errormsg = "The non-number " + somestring + " was";
                errormsg += " encountered while reading region " + regionname;
                errormsg += " in file " + filename + " on line ";
                errormsg += ToString(linenumber);
                throw FileFormatError (errormsg);
            }
            skipWhiteSpace(linestream);
        }

        line.erase();
        notdone = getLine(spacefile,line);
        ++linenumber;
    }
    // add the last region to the map
    spacings.insert(make_pair(regionname,positions));

#ifndef GUI
    ValidateSpaceInfo(spacings,filename);
#endif

    return spacings;

} // SpaceConverter::ReadSpacingInfo

//----------------------------------------------------------------------

void SpaceConverter::addConvertedLamarcDS(LamarcDS& lamarc)
{
    lamarc.mergeTo(m_lamarc);
} // SpaceConverter::addConvertedLamarcDS

//____________________________________________________________________________________
