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

#include "AppPlatformShellCommands-JNI.h"
#include "AppImpl.h"
#include "TvApp-JNI.h"
#include <access/AccessControl.h>
#include <jni.h>
#include <lib/core/CHIPError.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/JniReferences.h>
#include <lib/support/JniTypeWrappers.h>

#include <string>

#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
#include <app/app-platform/ContentAppPlatform.h>
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED

using namespace chip;

char response[1024];

using namespace ::chip::Controller;
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
using namespace chip::AppPlatform;
using namespace chip::Access;
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
using namespace chip::app::Clusters;

#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED

static CHIP_ERROR pairApp(bool printHeader, size_t index)
{

    if (printHeader)
    {
        char str[64];
        sprintf(str, "udc-commission %ld\r\n", static_cast<long>(index));
        strcat(response, str);
    }

    DeviceCommissioner * commissioner = GetDeviceCommissioner();
    UDCClientState * state = commissioner->GetUserDirectedCommissioningServer()->GetUDCClients().GetUDCClientState(index);
    if (state == nullptr)
    {
        char str[64];
        sprintf(str, "udc client[%ld] null \r\n", static_cast<long>(index));
        strcat(response, str);
    }
    else
    {
        ContentApp * app = ContentAppPlatform::GetInstance().LoadContentAppByClient(state->GetVendorId(), state->GetProductId());
        if (app == nullptr)
        {
            char str[64];
            sprintf(str, "no app found for vendor id=%d \r\n", state->GetVendorId());
            strcat(response, str);
            return CHIP_ERROR_BAD_REQUEST;
        }

        if (app->GetAccountLoginDelegate() == nullptr)
        {
            char str[64];
            sprintf(str, "no AccountLogin cluster for app with vendor id=%d \r\n", state->GetVendorId());
            strcat(response, str);
            return CHIP_ERROR_BAD_REQUEST;
        }

        char rotatingIdString[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
        Encoding::BytesToUppercaseHexString(state->GetRotatingId(), state->GetRotatingIdLength(), rotatingIdString,
                                            sizeof(rotatingIdString));

        CharSpan rotatingIdSpan = CharSpan(rotatingIdString, strlen(rotatingIdString));

        static const size_t kSetupPinSize = 12;
        char setupPin[kSetupPinSize];

        app->GetAccountLoginDelegate()->GetSetupPin(setupPin, kSetupPinSize, rotatingIdSpan);
        std::string pinString(setupPin);

        char * eptr;
        uint32_t pincode = (uint32_t) strtol(pinString.c_str(), &eptr, 10);
        if (pincode == 0)
        {
            char str[64];
            sprintf(str, "udc no pin returned for vendor id=%d rotating ID=%s \r\n", state->GetVendorId(), rotatingIdString);
            strcat(response, str);
            return CHIP_ERROR_BAD_REQUEST;
        }

        return CommissionerPairUDC(pincode, index);
    }
    return CHIP_NO_ERROR;
}

void DumpAccessControlEntry(const Access::AccessControl::Entry & entry)
{

    CHIP_ERROR err;

    {
        FabricIndex fabricIndex;
        SuccessOrExit(err = entry.GetFabricIndex(fabricIndex));
        char str[64];
        sprintf(str, "fabricIndex: %u\n", fabricIndex);
        strcat(response, str);
    }

    {
        Privilege privilege;
        SuccessOrExit(err = entry.GetPrivilege(privilege));
        char str[64];
        sprintf(str, "privilege: %d\n", to_underlying(privilege));
        strcat(response, str);
    }

    {
        AuthMode authMode;
        SuccessOrExit(err = entry.GetAuthMode(authMode));
        char str[64];
        sprintf(str, "authMode: %d\n", to_underlying(authMode));
        strcat(response, str);
    }

    {
        size_t count;
        SuccessOrExit(err = entry.GetSubjectCount(count));
        if (count)
        {

            char str[64];
            sprintf(str, "subjects: %u\n", static_cast<unsigned>(count));
            strcat(response, str);

            for (size_t i = 0; i < count; ++i)
            {
                NodeId subject;
                SuccessOrExit(err = entry.GetSubject(i, subject));

                char buffer[64];
                sprintf(buffer, "  %u: 0x" ChipLogFormatX64, static_cast<unsigned>(i), ChipLogValueX64(subject));
                strcat(response, buffer);
            }
        }
    }

    {
        size_t count;
        SuccessOrExit(err = entry.GetTargetCount(count));
        if (count)
        {

            char str[64];
            sprintf(str, "\ntargets: %u\n", static_cast<unsigned>(count));
            strcat(response, str);

            for (size_t i = 0; i < count; ++i)
            {
                Access::AccessControl::Entry::Target target;
                SuccessOrExit(err = entry.GetTarget(i, target));
                char buffer[64];
                if (target.flags & Access::AccessControl::Entry::Target::kCluster)
                {
                    sprintf(buffer, "  %u: cluster: 0x" ChipLogFormatMEI, static_cast<unsigned>(i),
                            ChipLogValueMEI(target.cluster));
                    strcat(buffer, "\n");
                    strcat(response, buffer);
                }
                if (target.flags & Access::AccessControl::Entry::Target::kEndpoint)
                {
                    sprintf(buffer, "  %u: endpoint: %u", static_cast<unsigned>(i), target.endpoint);
                    strcat(buffer, "\n");
                    strcat(response, buffer);
                }
                if (target.flags & Access::AccessControl::Entry::Target::kDeviceType)
                {
                    sprintf(buffer, "  %u: deviceType: 0x" ChipLogFormatMEI, static_cast<unsigned>(i),
                            ChipLogValueMEI(target.deviceType));
                    strcat(buffer, "\n");
                    strcat(response, buffer);
                }
            }
        }
    }

    strcat(response, "----- END ENTRY -----\n");

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "DumpAccessControlEntry: dump failed %" CHIP_ERROR_FORMAT, err.Format());
        strcpy(response, "Error occurred");
    }
}

char * AppPlatformHandler(int argc, char ** argv)
{
    CHIP_ERROR err;

    if (argc == 0 || strcmp(argv[0], "help") == 0)
    {
        strcpy(response, "check usage instructions on the UI");
    }
    else if (strcmp(argv[0], "add-admin-vendor") == 0)
    {
        if (argc < 2)
        {
            strcpy(response, "check usage instructions on the UI");
        }
        char * eptr;

        uint16_t vid                    = (uint16_t) strtol(argv[1], &eptr, 10);
        ContentAppFactoryImpl * factory = GetContentAppFactoryImpl();
        factory->AddAdminVendorId(vid);

        ChipLogProgress(DeviceLayer, "added admin-vendor");

        strcpy(response, "added admin-vendor");

        return response;
    }
    else if (strcmp(argv[0], "add") == 0)
    {
        if (argc < 2)
        {
            strcpy(response, "check usage instructions on the UI");
        }
        char * eptr;

        uint16_t vid = (uint16_t) strtol(argv[1], &eptr, 10);
        uint16_t pid = 0;
        if (argc >= 3)
        {
            pid = (uint16_t) strtol(argv[2], &eptr, 10);
        }
        ContentAppPlatform::GetInstance().LoadContentAppByClient(vid, pid);

        ChipLogProgress(DeviceLayer, "added app");

        strcpy(response, "added app");

        return response;
    }
    else if (strcmp(argv[0], "print-app-access") == 0)
    {
        Access::AccessControl::EntryIterator iterator;
        SuccessOrExit(err = Access::GetAccessControl().Entries(GetDeviceCommissioner()->GetFabricIndex(), iterator));
        // clear entry
        strcpy(response, "");
        Access::AccessControl::Entry entry;
        while (iterator.Next(entry) == CHIP_NO_ERROR)
        {
            DumpAccessControlEntry(entry);
        }
        return response;
    }
    else if (strcmp(argv[0], "remove-app-access") == 0)
    {
        Access::GetAccessControl().DeleteAllEntriesForFabric(GetDeviceCommissioner()->GetFabricIndex());
        strcpy(response, "removed app access");

        return response;
    }
    else if (strcmp(argv[0], "remove") == 0)
    {
        if (argc < 2)
        {
            strcpy(response, "check usage instructions on the UI");
        }
        char * eptr;

        uint16_t endpoint = (uint16_t) strtol(argv[1], &eptr, 10);
        ContentApp * app  = ContentAppPlatform::GetInstance().GetContentApp(endpoint);
        if (app == nullptr)
        {
            ChipLogProgress(DeviceLayer, "app not found");

            strcpy(response, "app not found");
            return response;
        }
        ContentAppPlatform::GetInstance().RemoveContentApp(app);

        ChipLogProgress(DeviceLayer, "removed app");

        strcpy(response, "removed app");

        return response;
    }
    else if (strcmp(argv[0], "setpin") == 0)
    {
        if (argc < 3)
        {
            strcpy(response, "check usage instructions on the UI");
        }
        char * eptr;

        uint16_t endpoint = (uint16_t) strtol(argv[1], &eptr, 10);
        char * pincode    = argv[2];
        ContentApp * app  = ContentAppPlatform::GetInstance().GetContentApp(endpoint);
        if (app == nullptr)
        {
            ChipLogProgress(DeviceLayer, "app not found");
            strcpy(response, "app not found");
            return response;
        }
        if (app->GetAccountLoginDelegate() == nullptr)
        {
            ChipLogProgress(DeviceLayer, "no AccountLogin cluster for app with endpoint id=%d ", endpoint);

            strcpy(response, "no AccountLogin cluster for app with endpoint");
            return response;
        }
        app->GetAccountLoginDelegate()->SetSetupPin(pincode);

        ChipLogProgress(DeviceLayer, "set pin success");

        strcpy(response, "set pin success");

        return response;
    }
    else if (strcmp(argv[0], "commission") == 0)
    {
        if (argc < 2)
        {
            strcpy(response, "check usage instructions on the UI");
        }
        char * eptr;
        size_t index = (size_t) strtol(argv[1], &eptr, 10);
        SuccessOrExit(err = pairApp(true, index));
        return response;
    }
    else
    {
        strcpy(response, "invalid argument");
        return response;
    }
    return response;
exit:
    ChipLogError(DeviceLayer, "Error: %" CHIP_ERROR_FORMAT, err.Format());
    strcpy(response, "Error occurred");
    return response;
}

#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED

#define JNI_METHOD(RETURN, METHOD_NAME)                                                                                            \
    extern "C" JNIEXPORT RETURN JNICALL Java_com_matter_tv_server_tvapp_AppPlatformShellCommands_##METHOD_NAME

JNI_METHOD(jstring, OnExecuteCommand)(JNIEnv * env, jobject, jobjectArray stringArray)
{
    int argc     = env->GetArrayLength(stringArray);
    char ** argv = new char *[(uint) argc];

    // Fill in argv
    for (int i = 0; i < argc; i++)
    {
        jstring string = (jstring) (env->GetObjectArrayElement(stringArray, i));
        argv[i]        = (char *) env->GetStringUTFChars(string, 0);
    }

    // Store response to show it to the users
    char * buf = AppPlatformHandler(argc, argv);

    // Release UTF Chars
    for (int i = 0; i < argc; i++)
    {
        ChipLogProgress(DeviceLayer, " Value=%s ", argv[i]);
        jstring string = (jstring) (env->GetObjectArrayElement(stringArray, i));
        env->ReleaseStringUTFChars(string, argv[i]);
    }

    return env->NewStringUTF(buf);
}
