//------------------------------------------------------------------------------
/*
    Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================

#define SECTION_DEFAULT_NAME    ""

struct ParseSectionLog; // for Log

SETUP_LOGN (ParseSectionLog,"ParseSection")

Section ParseSection (const std::string& strInput, const bool bTrim)
{
    std::string strData (strInput);
    std::vector<std::string> vLines;
    Section secResult;

    // Convert DOS format to unix.
    boost::algorithm::replace_all (strData, "\r\n", "\n");

    // Convert MacOS format to unix.
    boost::algorithm::replace_all (strData, "\r", "\n");

    boost::algorithm::split (vLines, strData, boost::algorithm::is_any_of ("\n"));

    // Set the default Section name.
    std::string strSection  = SECTION_DEFAULT_NAME;

    // Initialize the default Section.
    secResult[strSection]   = Section::mapped_type ();

    // Parse each line.
    BOOST_FOREACH (std::string & strValue, vLines)
    {
        if (strValue.empty () || strValue[0] == '#')
        {
            // Blank line or comment, do nothing.

            nothing ();
        }
        else if (strValue[0] == '[' && strValue[strValue.length () - 1] == ']')
        {
            // New Section.

            strSection              = strValue.substr (1, strValue.length () - 2);
            secResult[strSection]   = Section::mapped_type ();
        }
        else
        {
            // Another line for Section.
            if (bTrim)
                boost::algorithm::trim (strValue);

            if (!strValue.empty ())
                secResult[strSection].push_back (strValue);
        }
    }

    return secResult;
}

void SectionEntriesPrint (std::vector<std::string>* vspEntries, const std::string& strSection)
{
    Log::out() << "[" << strSection << "]";

    if (vspEntries)
    {
        BOOST_FOREACH (std::string & strValue, *vspEntries)
        {
            Log::out() << strValue;
        }
    }
}

void SectionPrint (Section secInput)
{
    BOOST_FOREACH (Section::value_type & pairSection, secInput)
    {
        SectionEntriesPrint (&pairSection.second, pairSection.first);
    }
}

Section::mapped_type* SectionEntries (Section& secSource, const std::string& strSection)
{
    Section::iterator       it;
    Section::mapped_type*   smtResult;

    it  = secSource.find (strSection);

    if (it == secSource.end ())
    {
        smtResult   = 0;
    }
    else
    {
        //Section::mapped_type& vecEntries  = it->second;

        smtResult   = & (it->second);
    }

    return smtResult;
}

int SectionCount (Section& secSource, const std::string& strSection)
{
    Section::mapped_type* pmtEntries    = SectionEntries (secSource, strSection);

    return pmtEntries ? pmtEntries->size () : 0;
}

bool SectionSingleB (Section& secSource, const std::string& strSection, std::string& strValue)
{
    Section::mapped_type*   pmtEntries  = SectionEntries (secSource, strSection);
    bool                    bSingle     = pmtEntries && 1 == pmtEntries->size ();

    if (bSingle)
    {
        strValue    = (*pmtEntries)[0];
    }
    else if (pmtEntries)
    {
        WriteLog (lsWARNING, ParseSectionLog) << boost::str (boost::format ("Section [%s]: requires 1 line not %d lines.")
                                              % strSection
                                              % pmtEntries->size ());
    }

    return bSingle;
}

StringPairArray parseKeyValueSection (Section& secSource, String const& strSection)
{
    StringPairArray result;

    // yuck.
    std::string const stdStrSection (strSection.toStdString ());

    typedef Section::mapped_type Entries;

    Entries* const entries = SectionEntries (secSource, stdStrSection);

    if (entries != nullptr)
    {
        for (Entries::const_iterator iter = entries->begin (); iter != entries->end (); ++iter)
        {
            String const line (iter->c_str ());

            int const equalPos = line.indexOfChar ('=');

            if (equalPos != -1)
            {
                String const key = line.substring (0, equalPos);
                String const value = line.substring (equalPos + 1, line.length ());

                result.set (key, value);
            }
        }
    }

    return result;
}

