/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

#include <log4cxx/logstring.h>
#include <log4cxx/helpers/properties.h>
#include <log4cxx/helpers/inputstreamreader.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/pool.h>

using namespace log4cxx;
using namespace log4cxx::helpers;

class PropertyParser
{
    public:
        void parse(LogString& in, Properties& properties)
        {
            LogString key, element;
            LexemType lexemType = BEGIN;
            logchar c;
            bool finished = false;

            if (!get(in, c))
            {
                return;
            }

            while (!finished)
            {
                switch (lexemType)
                {
                    case BEGIN:
                        switch (c)
                        {
                            case 0x20: // ' '
                            case 0x09: // '\t'
                            case 0x0A: // '\n'
                            case 0x0D: // '\r'
                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            case 0x23: // '#'
                            case 0x21: // '!'
                                lexemType = COMMENT;

                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            default:
                                lexemType = KEY;
                                break;
                        }

                        break;

                    case KEY:
                        switch (c)
                        {
                            case 0x5C: // '\\'
                                lexemType = KEY_ESCAPE;

                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            case 0x09: // '\t'
                            case 0x20: // ' '
                            case 0x3A: // ':'
                            case 0x3D: // '='
                                lexemType = DELIMITER;

                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            case 0x0A:
                            case 0x0D:
                                // key associated with an empty string element
                                properties.setProperty(key, LogString());
                                key.erase(key.begin(), key.end());
                                lexemType = BEGIN;

                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            default:
                                key.append(1, c);

                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;
                        }

                        break;

                    case KEY_ESCAPE:
                        switch (c)
                        {
                            case 0x74: // 't'
                                key.append(1, 0x09);
                                lexemType = KEY;
                                break;

                            case 0x6E: // 'n'
                                key.append(1, 0x0A);
                                lexemType = KEY;
                                break;

                            case 0x72: // 'r'
                                key.append(1, 0x0D);
                                lexemType = KEY;
                                break;

                            case 0x0A: // '\n'
                                lexemType = KEY_CONTINUE;
                                break;

                            case 0x0D: // '\r'
                                lexemType = KEY_CONTINUE2;
                                break;

                            default:
                                key.append(1, c);
                                lexemType = KEY;
                        }

                        if (!get(in, c))
                        {
                            finished = true;
                        }

                        break;

                    case KEY_CONTINUE:
                        switch (c)
                        {
                            case 0x20:  // ' '
                            case 0x09: //  '\t'
                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            default:
                                lexemType = KEY;
                                break;
                        }

                        break;

                    case KEY_CONTINUE2:
                        switch (c)
                        {
                            case 0x0A: // '\n'
                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                lexemType = KEY_CONTINUE;
                                break;

                            default:
                                lexemType = KEY_CONTINUE;
                                break;
                        }

                        break;

                    case DELIMITER:
                        switch (c)
                        {
                            case 0x09: // '\t'
                            case 0x20: // ' '
                            case 0x3A: // ':'
                            case 0x3D: // '='
                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            default:
                                lexemType = ELEMENT;
                                break;
                        }

                        break;

                    case ELEMENT:
                        switch (c)
                        {
                            case 0x5C: // '\\'
                                lexemType = ELEMENT_ESCAPE;

                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            case 0x0A: // '\n'
                            case 0x0D: // '\r'
                                // key associated with an empty string element
                                properties.setProperty(key, element);
                                key.erase(key.begin(), key.end());
                                element.erase(element.begin(), element.end());
                                lexemType = BEGIN;

                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            default:
                                element.append(1, c);

                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;
                        }

                        break;

                    case ELEMENT_ESCAPE:
                        switch (c)
                        {
                            case 0x74: // 't'
                                element.append(1, 0x09);
                                lexemType = ELEMENT;
                                break;

                            case 0x6E: // 'n'
                                element.append(1, 0x0A);
                                lexemType = ELEMENT;
                                break;

                            case 0x72: // 'r'
                                element.append(1, 0x0D);
                                lexemType = ELEMENT;
                                break;

                            case 0x0A: // '\n'
                                lexemType = ELEMENT_CONTINUE;
                                break;

                            case 0x0D: // '\r'
                                lexemType = ELEMENT_CONTINUE2;
                                break;

                            default:
                                element.append(1, c);
                                lexemType = ELEMENT;
                                break;
                        }

                        if (!get(in, c))
                        {
                            finished = true;
                        }

                        break;

                    case ELEMENT_CONTINUE:
                        switch (c)
                        {
                            case 0x20: // ' '
                            case 0x09: // '\t'
                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                break;

                            default:
                                lexemType = ELEMENT;
                                break;
                        }

                        break;

                    case ELEMENT_CONTINUE2:
                        switch (c)
                        {
                            case 0x0A: // '\n'
                                if (!get(in, c))
                                {
                                    finished = true;
                                }

                                lexemType = ELEMENT_CONTINUE;
                                break;

                            default:
                                lexemType = ELEMENT_CONTINUE;
                                break;
                        }

                        break;

                    case COMMENT:
                        if (c == 0x0A || c == 0x0D)
                        {
                            lexemType = BEGIN;
                        }

                        if (!get(in, c))
                        {
                            finished = true;
                        }

                        break;
                }
            }

            if (!key.empty())
            {
                properties.setProperty(key, element);
            }
        }

    protected:
        static bool get(LogString& in, logchar& c)
        {
            if (in.empty())
            {
                c = 0;
                return false;
            }

            c = in[0];
            in.erase(in.begin());
            return true;
        }

        typedef enum
        {
            BEGIN,
            KEY,
            KEY_ESCAPE,
            KEY_CONTINUE,
            KEY_CONTINUE2,
            DELIMITER,
            ELEMENT,
            ELEMENT_ESCAPE,
            ELEMENT_CONTINUE,
            ELEMENT_CONTINUE2,
            COMMENT
        }
        LexemType;
};

Properties::Properties() : properties(new PropertyMap())
{
}

Properties::~Properties()
{
    delete properties;
}

LogString Properties::setProperty(const LogString& key, const LogString& value)
{
    return put(key, value);
}

LogString Properties::put(const LogString& key, const LogString& value)
{
    LogString oldValue((*properties)[key]);
    (*properties)[key] = value;
    return oldValue;
}

LogString Properties::getProperty(const LogString& key) const
{
    return get(key);
}

LogString Properties::get(const LogString& key) const
{
    PropertyMap::const_iterator it = properties->find(key);
    return (it != properties->end()) ? it->second : LogString();
}

void Properties::load(InputStreamPtr inStream)
{
    Pool pool;
    InputStreamReaderPtr lineReader(
        new InputStreamReader(inStream, CharsetDecoder::getISOLatinDecoder()));
    LogString contents = lineReader->read(pool);
    properties->clear();
    PropertyParser parser;
    parser.parse(contents, *this);
}

std::vector<LogString> Properties::propertyNames() const
{
    std::vector<LogString> names;
    names.reserve(properties->size());

    PropertyMap::const_iterator it;

    for (it = properties->begin(); it != properties->end(); it++)
    {
        const LogString& key = it->first;
        names.push_back(key);
    }

    return names;
}

