/*
 * Copyright (C) 2018 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#if ENABLE(WEB_AUTHN)

#include "AttestationConveyancePreference.h"
#include "AuthenticationExtensionsClientInputs.h"
#include "BufferSource.h"
#include "PublicKeyCredentialDescriptor.h"
#include "PublicKeyCredentialType.h"
#include "UserVerificationRequirement.h"
#include <wtf/CrossThreadCopier.h>
#include <wtf/Forward.h>

namespace WebCore {

struct PublicKeyCredentialCreationOptions {
    enum class AuthenticatorAttachment {
        Platform,
        CrossPlatform
    };

    struct Entity {
        String name;
        String icon;
    };

    struct RpEntity : public Entity {
        mutable String id;
    };

    struct UserEntity : public Entity {
        BufferSource id; // id becomes idVector once it is passed to UIProcess.
        Vector<uint8_t> idVector;
        String displayName;
    };

    struct Parameters {
        PublicKeyCredentialType type;
        int64_t alg;

        template<class Encoder> void encode(Encoder&) const;
        template<class Decoder> static Optional<Parameters> decode(Decoder&);
    };

    struct AuthenticatorSelectionCriteria {
        Optional<AuthenticatorAttachment> authenticatorAttachment;
        bool requireResidentKey { false };
        UserVerificationRequirement userVerification { UserVerificationRequirement::Preferred };

        template<class Encoder> void encode(Encoder&) const;
        template<class Decoder> static Optional<AuthenticatorSelectionCriteria> decode(Decoder&);
    };

    RpEntity rp;
    UserEntity user;

    BufferSource challenge;
    Vector<Parameters> pubKeyCredParams;

    Optional<unsigned> timeout;
    Vector<PublicKeyCredentialDescriptor> excludeCredentials;
    Optional<AuthenticatorSelectionCriteria> authenticatorSelection;
    AttestationConveyancePreference attestation;
    mutable Optional<AuthenticationExtensionsClientInputs> extensions;

    template<class Encoder> void encode(Encoder&) const;
    template<class Decoder> static Optional<PublicKeyCredentialCreationOptions> decode(Decoder&);
};

template<class Encoder>
void PublicKeyCredentialCreationOptions::Parameters::encode(Encoder& encoder) const
{
    encoder << type << alg;
}

template<class Decoder>
Optional<PublicKeyCredentialCreationOptions::Parameters> PublicKeyCredentialCreationOptions::Parameters::decode(Decoder& decoder)
{
    PublicKeyCredentialCreationOptions::Parameters result;
    if (!decoder.decodeEnum(result.type))
        return WTF::nullopt;
    if (!decoder.decode(result.alg))
        return WTF::nullopt;
    return result;
}

template<class Encoder>
void PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria::encode(Encoder& encoder) const
{
    encoder << authenticatorAttachment << requireResidentKey << userVerification;
}

template<class Decoder>
Optional<PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria> PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria::decode(Decoder& decoder)
{
    PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria result;

    Optional<Optional<AuthenticatorAttachment>> authenticatorAttachment;
    decoder >> authenticatorAttachment;
    if (!authenticatorAttachment)
        return WTF::nullopt;
    result.authenticatorAttachment = WTFMove(*authenticatorAttachment);

    Optional<bool> requireResidentKey;
    decoder >> requireResidentKey;
    if (!requireResidentKey)
        return WTF::nullopt;
    result.requireResidentKey = *requireResidentKey;

    if (!decoder.decodeEnum(result.userVerification))
        return WTF::nullopt;
    return result;
}

// Not every member is encoded.
template<class Encoder>
void PublicKeyCredentialCreationOptions::encode(Encoder& encoder) const
{
    encoder << rp.id << rp.name << rp.icon;
    encoder << static_cast<uint64_t>(user.id.length());
    encoder.encodeFixedLengthData(user.id.data(), user.id.length(), 1);
    encoder << user.displayName << user.name << user.icon << pubKeyCredParams << timeout << excludeCredentials << authenticatorSelection << attestation << extensions;
}

template<class Decoder>
Optional<PublicKeyCredentialCreationOptions> PublicKeyCredentialCreationOptions::decode(Decoder& decoder)
{
    PublicKeyCredentialCreationOptions result;
    if (!decoder.decode(result.rp.id))
        return WTF::nullopt;
    if (!decoder.decode(result.rp.name))
        return WTF::nullopt;
    if (!decoder.decode(result.rp.icon))
        return WTF::nullopt;
    if (!decoder.decode(result.user.idVector))
        return WTF::nullopt;
    if (!decoder.decode(result.user.displayName))
        return WTF::nullopt;
    if (!decoder.decode(result.user.name))
        return WTF::nullopt;
    if (!decoder.decode(result.user.icon))
        return WTF::nullopt;
    if (!decoder.decode(result.pubKeyCredParams))
        return WTF::nullopt;

    Optional<Optional<unsigned>> timeout;
    decoder >> timeout;
    if (!timeout)
        return WTF::nullopt;
    result.timeout = WTFMove(*timeout);

    if (!decoder.decode(result.excludeCredentials))
        return WTF::nullopt;

    Optional<Optional<AuthenticatorSelectionCriteria>> authenticatorSelection;
    decoder >> authenticatorSelection;
    if (!authenticatorSelection)
        return WTF::nullopt;
    result.authenticatorSelection = WTFMove(*authenticatorSelection);

    Optional<AttestationConveyancePreference> attestation;
    decoder >> attestation;
    if (!attestation)
        return WTF::nullopt;
    result.attestation = WTFMove(*attestation);

    Optional<Optional<AuthenticationExtensionsClientInputs>> extensions;
    decoder >> extensions;
    if (!extensions)
        return WTF::nullopt;
    result.extensions = WTFMove(*extensions);

    return result;
}

} // namespace WebCore

namespace WTF {

template<> struct EnumTraits<WebCore::PublicKeyCredentialCreationOptions::AuthenticatorAttachment> {
    using values = EnumValues<
        WebCore::PublicKeyCredentialCreationOptions::AuthenticatorAttachment,
        WebCore::PublicKeyCredentialCreationOptions::AuthenticatorAttachment::Platform,
        WebCore::PublicKeyCredentialCreationOptions::AuthenticatorAttachment::CrossPlatform
    >;
};

} // namespace WTF

#endif // ENABLE(WEB_AUTHN)
