//* Copyright 2017 The Dawn 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 "common/Assert.h"

#include "dawn_native/dawn_platform.h"
#include "dawn_native/DawnNative.h"
#include "dawn_native/ErrorData.h"
#include "dawn_native/ValidationUtils_autogen.h"

{% for type in by_category["object"] %}
    {% if not type.is_builder and type.name.canonical_case() not in ["buffer view", "texture view"] %}
        #include "dawn_native/{{type.name.CamelCase()}}.h"
    {% endif %}
{% endfor %}

namespace dawn_native {

    namespace {

        {% set methodsWithExtraValidation = (
            "CommandBufferBuilderGetResult",
        ) %}

        {% for type in by_category["object"] %}
            {% for method in native_methods(type) %}
                {% set suffix = as_MethodSuffix(type.name, method.name) %}

                //* Autogenerated part of the entry point validation
                //*  - Check that enum and bitmaks are in the correct range
                //*  - Check that builders have not been consumed already
                bool ValidateBase{{suffix}}(
                    {{-as_frontendType(type)}} self
                    {%- for arg in method.arguments -%}
                        , {{as_annotated_frontendType(arg)}}
                    {%- endfor -%}
                ) {
                    {% if type.is_builder and method.name.canonical_case() not in ("release", "reference") %}
                        if (!self->CanBeUsed()) {
                            self->GetDevice()->HandleError("Builder cannot be used after GetResult");
                            return false;
                        }
                    {% else %}
                        DAWN_UNUSED(self);
                    {% endif %}
                    bool error = false;
                    DAWN_UNUSED(error);
                    {% for arg in method.arguments %}
                        {% set cppType = as_cppType(arg.type.name) %}
                        {% set argName = as_varName(arg.name) %}
                        {% if arg.type.category in ["enum", "bitmask"] %}
                            MaybeError {{argName}}Valid = Validate{{cppType}}(static_cast<dawn::{{cppType}}>({{argName}}));
                            if ({{argName}}Valid.IsError()) {
                                delete {{argName}}Valid.AcquireError();
                                error = true;
                            }
                        {% else %}
                            DAWN_UNUSED({{argName}});
                        {% endif %}
                        if (error) {
                            {% if type.is_builder %}
                                self->HandleError("Bad value in {{suffix}}");
                            {% else %}
                                self->GetDevice()->HandleError("Bad value in {{suffix}}");
                            {% endif %}
                            return false;
                        }
                    {% endfor %}
                    return true;
                }

                //* Entry point with validation
                {{as_frontendType(method.return_type)}} Validating{{suffix}}(
                    {{-as_frontendType(type)}} self
                    {%- for arg in method.arguments -%}
                        , {{as_annotated_frontendType(arg)}}
                    {%- endfor -%}
                ) {
                    //* Do the autogenerated checks
                    bool valid = ValidateBase{{suffix}}(self
                        {%- for arg in method.arguments -%}
                            , {{as_varName(arg.name)}}
                        {%- endfor -%}
                    );

                    //* Some function have very heavy checks in a separate method, so that they
                    //* can be skipped in the NonValidatingEntryPoints.
                    {% if suffix in methodsWithExtraValidation %}
                        if (valid) {
                            MaybeError error = self->Validate{{method.name.CamelCase()}}(
                                {%- for arg in method.arguments -%}
                                    {% if not loop.first %}, {% endif %}{{as_varName(arg.name)}}
                                {%- endfor -%}
                            );
                            //* Builders want to handle error themselves, unpack the error and make
                            //* the builder handle it.
                            {% if type.is_builder %}
                                if (error.IsError()) {
                                    ErrorData* errorData = error.AcquireError();
                                    self->HandleError(errorData->GetMessage().c_str());
                                    delete errorData;
                                    valid = false;
                                }
                            {% else %}
                                //* Non-builder errors are handled by the device
                                valid = !self->GetDevice()->ConsumedError(std::move(error));
                            {% endif %}
                        }
                    {% endif %}

                    //* HACK(cwallez@chromium.org): special casing GetResult so that the error callback
                    //* is called if needed. Without this, no call to HandleResult would happen, and the
                    //* error callback would always get called with an Unknown status
                    {% if type.is_builder and method.name.canonical_case() == "get result" %}
                        if (!valid) {
                            {{as_frontendType(method.return_type)}} fakeResult = nullptr;
                            bool shouldBeFalse = self->HandleResult(fakeResult);
                            ASSERT(shouldBeFalse == false);
                        }
                    {% endif %}

                    {% if method.return_type.name.canonical_case() == "void" %}
                        if (!valid) return;
                    {% else %}
                        if (!valid) {
                            return {};
                        }
                        auto result =
                    {%- endif %}
                    self->{{method.name.CamelCase()}}(
                        {%- for arg in method.arguments -%}
                            {%- if not loop.first %}, {% endif -%}
                            {%- if arg.type.category in ["enum", "bitmask"] -%}
                                static_cast<dawn::{{as_cppType(arg.type.name)}}>({{as_varName(arg.name)}})
                            {%- elif arg.type.category == "structure" and arg.annotation != "value" -%}
                                reinterpret_cast<const {{as_cppType(arg.type.name)}}*>({{as_varName(arg.name)}})
                            {%- else -%}
                                {{as_varName(arg.name)}}
                            {%- endif -%}
                        {%- endfor -%}
                    );
                    {% if method.return_type.name.canonical_case() != "void" %}
                        return reinterpret_cast<{{as_frontendType(method.return_type)}}>(result);
                    {% endif %}
                }
            {% endfor %}
        {% endfor %}
    }

    dawnProcTable GetProcsAutogen() {
        dawnProcTable table;
        {% for type in by_category["object"] %}
            {% for method in native_methods(type) %}
                table.{{as_varName(type.name, method.name)}} = reinterpret_cast<{{as_cProc(type.name, method.name)}}>(Validating{{as_MethodSuffix(type.name, method.name)}});
            {% endfor %}
        {% endfor %}
        return table;
    }
}
