/*
 *   Copyright (c) 2022 Project CHIP Authors
 *   All rights reserved.
 *
 *   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.
 *
 */

#pragma once

#include <json/json.h>
#include <lib/core/Optional.h>

#include <memory>
#include <sstream>
#include <string>
#include <vector>

class JsonParser
{
public:
    // Returns whether the parse succeeded.
    static bool ParseComplexArgument(const char * label, const char * json, Json::Value & value)
    {
        return Parse(label, json, /* strictRoot = */ true, value);
    }

    // Returns whether the parse succeeded.
    static bool ParseCustomArgument(const char * label, const char * json, Json::Value & value)
    {
        return Parse(label, json, /* strictRoot = */ false, value);
    }

private:
    static bool Parse(const char * label, const char * json, bool strictRoot, Json::Value & value)
    {
        Json::CharReaderBuilder readerBuilder;
        readerBuilder.settings_["strictRoot"]        = strictRoot;
        readerBuilder.settings_["allowSingleQuotes"] = true;
        readerBuilder.settings_["failIfExtra"]       = true;
        readerBuilder.settings_["rejectDupKeys"]     = true;

        auto reader = std::unique_ptr<Json::CharReader>(readerBuilder.newCharReader());
        std::string errors;
        if (reader->parse(json, json + strlen(json), &value, &errors))
        {
            return true;
        }

        // The CharReader API allows us to set failIfExtra, unlike Reader, but does
        // not allow us to get structured errors.  We get to try to manually undo
        // the work it did to create a string from the structured errors it had.
        ChipLogError(chipTool, "Error parsing JSON for %s:", label);

        // For each error "errors" has the following:
        //
        // 1) A line starting with "* " that has line/column info
        // 2) A line with the error message.
        // 3) An optional line with some extra info.
        //
        // We keep track of the last error column, in case the error message
        // reporting needs it.
        std::istringstream stream(errors);
        std::string error;
        chip::Optional<unsigned> errorColumn;
        while (getline(stream, error))
        {
            if (error.rfind("* ", 0) == 0)
            {
                // Flush out any pending error location.
                LogErrorLocation(errorColumn, json);

                // The format of this line is:
                //
                // * Line N, Column M
                //
                // Unfortunately it does not indicate end of error, so we can only
                // show its start.
                unsigned errorLine; // ignored in practice
                if (sscanf(error.c_str(), "* Line %u, Column %u", &errorLine, &errorColumn.Emplace()) != 2)
                {
                    ChipLogError(chipTool, "Unexpected location string: %s\n", error.c_str());
                    // We don't know how to make sense of this thing anymore.
                    break;
                }
                if (errorColumn.Value() == 0)
                {
                    ChipLogError(chipTool, "Expected error column to be at least 1");
                    // We don't know how to make sense of this thing anymore.
                    break;
                }
                // We are using our column numbers as offsets, so want them to be
                // 0-based.
                --errorColumn.Value();
            }
            else
            {
                ChipLogError(chipTool, "  %s", error.c_str());
                if (error == "  Missing ',' or '}' in object declaration" && errorColumn.HasValue() && errorColumn.Value() > 0 &&
                    json[errorColumn.Value() - 1] == '0' && (json[errorColumn.Value()] == 'x' || json[errorColumn.Value()] == 'X'))
                {
                    // Log the error location marker before showing the NOTE
                    // message.
                    LogErrorLocation(errorColumn, json);
                    ChipLogError(chipTool,
                                 "NOTE: JSON does not allow hex syntax beginning with 0x for numbers.  Try putting the hex number "
                                 "in quotes (like {\"name\": \"0x100\"}).");
                }
            }
        }

        // Write out the marker for our last error.
        LogErrorLocation(errorColumn, json);

        return false;
    }

private:
    static void LogErrorLocation(chip::Optional<unsigned> & errorColumn, const char * json)
    {
        if (!errorColumn.HasValue())
        {
            return;
        }

        const char * sourceText = json;
        unsigned error_start    = errorColumn.Value();
        // The whole JSON string might be too long to fit in our log
        // messages.  Just include 30 chars before the error.
        constexpr ptrdiff_t kMaxContext = 30;
        std::string errorMarker;
        if (error_start > kMaxContext)
        {
            sourceText += (error_start - kMaxContext);
            error_start = kMaxContext;
            ChipLogError(chipTool, "... %s", sourceText);
            // Add markers corresponding to the "... " above.
            errorMarker += "----";
        }
        else
        {
            ChipLogError(chipTool, "%s", sourceText);
        }
        for (unsigned i = 0; i < error_start; ++i)
        {
            errorMarker += "-";
        }
        errorMarker += "^";
        ChipLogError(chipTool, "%s", errorMarker.c_str());
        errorColumn.ClearValue();
    }
};
