/*
 *   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 <app-common/zap-generated/cluster-objects.h>
#include <commands/common/HexConversion.h>
#include <lib/support/BytesToHex.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/SafeInt.h>

#include "JsonParser.h"

namespace {
static constexpr char kPayloadHexPrefix[]         = "hex:";
static constexpr char kPayloadSignedPrefix[]      = "s:";
static constexpr char kPayloadUnsignedPrefix[]    = "u:";
static constexpr char kPayloadFloatPrefix[]       = "f:";
static constexpr char kPayloadDoublePrefix[]      = "d:";
static constexpr size_t kPayloadHexPrefixLen      = ArraySize(kPayloadHexPrefix) - 1;      // ignore null character
static constexpr size_t kPayloadSignedPrefixLen   = ArraySize(kPayloadSignedPrefix) - 1;   // ignore null character
static constexpr size_t kPayloadUnsignedPrefixLen = ArraySize(kPayloadUnsignedPrefix) - 1; // ignore null character
static constexpr size_t kPayloadFloatPrefixLen    = ArraySize(kPayloadFloatPrefix) - 1;    // ignore null character
static constexpr size_t kPayloadDoublePrefixLen   = ArraySize(kPayloadDoublePrefix) - 1;   // ignore null character
} // namespace

class CustomArgumentParser
{
public:
    static CHIP_ERROR Put(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        if (value.isObject())
        {
            return CustomArgumentParser::PutObject(writer, tag, value);
        }

        if (value.isArray())
        {
            return CustomArgumentParser::PutArray(writer, tag, value);
        }

        if (value.isString())
        {
            if (IsOctetString(value))
            {
                return CustomArgumentParser::PutOctetString(writer, tag, value);
            }
            if (IsUnsignedNumberPrefix(value))
            {
                return CustomArgumentParser::PutUnsignedFromString(writer, tag, value);
            }
            if (IsSignedNumberPrefix(value))
            {
                return CustomArgumentParser::PutSignedFromString(writer, tag, value);
            }
            if (IsFloatNumberPrefix(value))
            {
                return CustomArgumentParser::PutFloatFromString(writer, tag, value);
            }
            if (IsDoubleNumberPrefix(value))
            {
                return CustomArgumentParser::PutDoubleFromString(writer, tag, value);
            }

            return CustomArgumentParser::PutCharString(writer, tag, value);
        }

        if (value.isNull())
        {
            return chip::app::DataModel::Encode(*writer, tag, chip::app::DataModel::Nullable<uint8_t>());
        }

        if (value.isBool())
        {
            return chip::app::DataModel::Encode(*writer, tag, value.asBool());
        }

        if (value.isUInt())
        {
            return chip::app::DataModel::Encode(*writer, tag, value.asLargestUInt());
        }

        if (value.isInt())
        {
            return chip::app::DataModel::Encode(*writer, tag, value.asLargestInt());
        }

        if (value.isNumeric())
        {
            return chip::app::DataModel::Encode(*writer, tag, value.asDouble());
        }

        return CHIP_ERROR_NOT_IMPLEMENTED;
    }

private:
    static CHIP_ERROR PutArray(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        chip::TLV::TLVType outer;
        ReturnErrorOnFailure(writer->StartContainer(tag, chip::TLV::kTLVType_Array, outer));

        Json::ArrayIndex size = value.size();

        for (Json::ArrayIndex i = 0; i < size; i++)
        {
            ReturnErrorOnFailure(CustomArgumentParser::Put(writer, chip::TLV::AnonymousTag(), value[i]));
        }

        return writer->EndContainer(outer);
    }

    static CHIP_ERROR PutObject(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        chip::TLV::TLVType outer;
        ReturnErrorOnFailure(writer->StartContainer(tag, chip::TLV::kTLVType_Structure, outer));

        for (auto const & id : value.getMemberNames())
        {
            auto index = std::stoul(id, nullptr, 0);
            VerifyOrReturnError(chip::CanCastTo<uint8_t>(index), CHIP_ERROR_INVALID_ARGUMENT);
            ReturnErrorOnFailure(CustomArgumentParser::Put(writer, chip::TLV::ContextTag(static_cast<uint8_t>(index)), value[id]));
        }

        return writer->EndContainer(outer);
    }

    static CHIP_ERROR PutOctetString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        const char * hexData = value.asCString() + kPayloadHexPrefixLen;
        size_t hexDataLen    = strlen(hexData);
        chip::Platform::ScopedMemoryBuffer<uint8_t> buffer;

        size_t octetCount;
        ReturnErrorOnFailure(HexToBytes(
            chip::CharSpan(hexData, hexDataLen),
            [&buffer](size_t allocSize) {
                buffer.Calloc(allocSize);
                return buffer.Get();
            },
            &octetCount));

        return chip::app::DataModel::Encode(*writer, tag, chip::ByteSpan(buffer.Get(), octetCount));
    }

    static CHIP_ERROR PutCharString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        size_t size = strlen(value.asCString());
        return chip::app::DataModel::Encode(*writer, tag, chip::CharSpan(value.asCString(), size));
    }

    static CHIP_ERROR PutUnsignedFromString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        char numberAsString[21];
        chip::Platform::CopyString(numberAsString, value.asCString() + kPayloadUnsignedPrefixLen);

        auto number = std::stoull(numberAsString, nullptr, 0);
        return chip::app::DataModel::Encode(*writer, tag, static_cast<uint64_t>(number));
    }

    static CHIP_ERROR PutSignedFromString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        char numberAsString[21];
        chip::Platform::CopyString(numberAsString, value.asCString() + kPayloadSignedPrefixLen);

        auto number = std::stoll(numberAsString, nullptr, 0);
        return chip::app::DataModel::Encode(*writer, tag, static_cast<int64_t>(number));
    }

    static CHIP_ERROR PutFloatFromString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        char numberAsString[21];
        chip::Platform::CopyString(numberAsString, value.asCString() + kPayloadFloatPrefixLen);

        auto number = std::stof(numberAsString);
        return chip::app::DataModel::Encode(*writer, tag, number);
    }

    static CHIP_ERROR PutDoubleFromString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value)
    {
        char numberAsString[21];
        chip::Platform::CopyString(numberAsString, value.asCString() + kPayloadDoublePrefixLen);

        auto number = std::stod(numberAsString);
        return chip::app::DataModel::Encode(*writer, tag, number);
    }

    static bool IsOctetString(Json::Value & value)
    {
        return (strncmp(value.asCString(), kPayloadHexPrefix, kPayloadHexPrefixLen) == 0);
    }

    static bool IsUnsignedNumberPrefix(Json::Value & value)
    {
        return (strncmp(value.asCString(), kPayloadUnsignedPrefix, kPayloadUnsignedPrefixLen) == 0);
    }

    static bool IsSignedNumberPrefix(Json::Value & value)
    {
        return (strncmp(value.asCString(), kPayloadSignedPrefix, kPayloadSignedPrefixLen) == 0);
    }

    static bool IsFloatNumberPrefix(Json::Value & value)
    {
        return (strncmp(value.asCString(), kPayloadFloatPrefix, kPayloadFloatPrefixLen) == 0);
    }

    static bool IsDoubleNumberPrefix(Json::Value & value)
    {
        return (strncmp(value.asCString(), kPayloadDoublePrefix, kPayloadDoublePrefixLen) == 0);
    }
};

class CustomArgument
{
public:
    ~CustomArgument()
    {
        if (mData != nullptr)
        {
            chip::Platform::MemoryFree(mData);
        }
    }

    CHIP_ERROR Parse(const char * label, const char * json)
    {
        Json::Value value;
        constexpr const char kHexNumPrefix[] = "0x";
        constexpr size_t kHexNumPrefixLen    = ArraySize(kHexNumPrefix) - 1;
        if (strncmp(json, kPayloadHexPrefix, kPayloadHexPrefixLen) == 0 ||
            strncmp(json, kPayloadSignedPrefix, kPayloadSignedPrefixLen) == 0 ||
            strncmp(json, kPayloadUnsignedPrefix, kPayloadUnsignedPrefixLen) == 0 ||
            strncmp(json, kPayloadFloatPrefix, kPayloadFloatPrefixLen) == 0 ||
            strncmp(json, kPayloadDoublePrefix, kPayloadDoublePrefixLen) == 0)
        {
            value = Json::Value(json);
        }
        else if (strncmp(json, kHexNumPrefix, kHexNumPrefixLen) == 0)
        {
            // Assume that hex numbers are unsigned.  Prepend
            // kPayloadUnsignedPrefix and then let the rest of the logic handle
            // things.
            std::string str(kPayloadUnsignedPrefix);
            str += json;
            value = Json::Value(str);
        }
        else if (!JsonParser::ParseCustomArgument(label, json, value))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }

        mData = static_cast<uint8_t *>(chip::Platform::MemoryCalloc(sizeof(uint8_t), mDataMaxLen));
        VerifyOrReturnError(mData != nullptr, CHIP_ERROR_NO_MEMORY);

        chip::TLV::TLVWriter writer;
        writer.Init(mData, mDataMaxLen);

        ReturnErrorOnFailure(CustomArgumentParser::Put(&writer, chip::TLV::AnonymousTag(), value));

        mDataLen = writer.GetLengthWritten();
        return writer.Finalize();
    }

    CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const
    {
        chip::TLV::TLVReader reader;
        reader.Init(mData, mDataLen);
        ReturnErrorOnFailure(reader.Next());

        return writer.CopyElement(tag, reader);
    }

    // We trust our consumers to do the encoding of our data correctly, so don't
    // need to know whether we are being encoded for a write.
    static constexpr bool kIsFabricScoped = false;

private:
    uint8_t * mData                       = nullptr;
    uint32_t mDataLen                     = 0;
    static constexpr uint32_t mDataMaxLen = 4096;
};
