/*
 *   Copyright (c) 2021-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 <commands/common/CredentialIssuerCommands.h>
#include <controller/CHIPDeviceControllerFactory.h>
#include <controller/ExampleOperationalCredentialsIssuer.h>
#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>

class ExampleCredentialIssuerCommands : public CredentialIssuerCommands
{
public:
    CHIP_ERROR InitializeCredentialsIssuer(chip::PersistentStorageDelegate & storage) override
    {
        return mOpCredsIssuer.Initialize(storage);
    }
    CHIP_ERROR SetupDeviceAttestation(chip::Controller::SetupParams & setupParams,
                                      const chip::Credentials::AttestationTrustStore * trustStore) override
    {
        chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider());

        mDacVerifier                          = chip::Credentials::GetDefaultDACVerifier(trustStore);
        setupParams.deviceAttestationVerifier = mDacVerifier;
        mDacVerifier->EnableCdTestKeySupport(mAllowTestCdSigningKey);

        return CHIP_NO_ERROR;
    }
    chip::Controller::OperationalCredentialsDelegate * GetCredentialIssuer() override { return &mOpCredsIssuer; }
    CHIP_ERROR GenerateControllerNOCChain(chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats,
                                          chip::Crypto::P256Keypair & keypair, chip::MutableByteSpan & rcac,
                                          chip::MutableByteSpan & icac, chip::MutableByteSpan & noc) override
    {
        return mOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, cats, keypair.Pubkey(), rcac, icac, noc);
    }

    CHIP_ERROR AddAdditionalCDVerifyingCerts(const std::vector<std::vector<uint8_t>> & additionalCdCerts) override
    {
        VerifyOrReturnError(mDacVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);

        for (const auto & cert : additionalCdCerts)
        {
            auto cdTrustStore = mDacVerifier->GetCertificationDeclarationTrustStore();
            VerifyOrReturnError(cdTrustStore != nullptr, CHIP_ERROR_INCORRECT_STATE);
            ReturnErrorOnFailure(cdTrustStore->AddTrustedKey(chip::ByteSpan(cert.data(), cert.size())));
        }

        return CHIP_NO_ERROR;
    }

    void SetCredentialIssuerOption(CredentialIssuerOptions option, bool isEnabled) override
    {
        switch (option)
        {
        case CredentialIssuerOptions::kMaximizeCertificateSizes:
            mUsesMaxSizedCerts = isEnabled;
            mOpCredsIssuer.SetMaximallyLargeCertsUsed(mUsesMaxSizedCerts);
            break;
        case CredentialIssuerOptions::kAllowTestCdSigningKey:
            mAllowTestCdSigningKey = isEnabled;
            if (mDacVerifier != nullptr)
            {
                mDacVerifier->EnableCdTestKeySupport(isEnabled);
            }

        default:
            break;
        }
    }

    bool GetCredentialIssuerOption(CredentialIssuerOptions option) override
    {
        switch (option)
        {
        case CredentialIssuerOptions::kMaximizeCertificateSizes:
            return mUsesMaxSizedCerts;
        case CredentialIssuerOptions::kAllowTestCdSigningKey:
            return mAllowTestCdSigningKey;
        default:
            return false;
        }
    }

protected:
    bool mUsesMaxSizedCerts = false;
    // Starts true for legacy purposes
    bool mAllowTestCdSigningKey = true;

private:
    chip::Controller::ExampleOperationalCredentialsIssuer mOpCredsIssuer;
    chip::Credentials::DeviceAttestationVerifier * mDacVerifier;
};
