//* Copyright 2019 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_wire/server/Server.h"

namespace dawn::wire::server {
    //* Implementation of the command doers
    {% for command in cmd_records["command"] %}
        {% set type = command.derived_object %}
        {% set method = command.derived_method %}
        {% set is_method = method is not none %}

        {% set Suffix = command.name.CamelCase() %}
        {% if Suffix not in client_side_commands %}
            {% if is_method and Suffix not in server_handwritten_commands %}
                bool Server::Do{{Suffix}}(
                    {%- for member in command.members -%}
                        {%- if member.is_return_value -%}
                            {%- if member.handle_type -%}
                                {{as_cType(member.handle_type.name)}}* {{as_varName(member.name)}}
                            {%- else -%}
                                {{as_cType(member.type.name)}}* {{as_varName(member.name)}}
                            {%- endif -%}
                        {%- else -%}
                            {{as_annotated_cType(member)}}
                        {%- endif -%}
                        {%- if not loop.last -%}, {% endif %}
                    {%- endfor -%}
                ) {
                    {% set ret = command.members|selectattr("is_return_value")|list %}
                    //* If there is a return value, assign it.
                    {% if ret|length == 1 %}
                        *{{as_varName(ret[0].name)}} =
                    {% else %}
                        //* Only one member should be a return value.
                        {{ assert(ret|length == 0) }}
                    {% endif %}
                    mProcs.{{as_varName(type.name, method.name)}}(
                        {%- for member in command.members if not member.is_return_value -%}
                            {{as_varName(member.name)}}
                            {%- if not loop.last -%}, {% endif %}
                        {%- endfor -%}
                    );
                    {% if ret|length == 1 %}
                        //* WebGPU error handling guarantees that no null object can be returned by
                        //* object creation functions.
                        ASSERT(*{{as_varName(ret[0].name)}} != nullptr);
                    {% endif %}
                    return true;
                }
            {% endif %}
        {% endif %}
    {% endfor %}

    bool Server::DoDestroyObject(ObjectType objectType, ObjectId objectId) {
        //* ID 0 are reserved for nullptr and cannot be destroyed.
        if (objectId == 0) {
            return false;
        }

        switch(objectType) {
            {% for type in by_category["object"] %}
                case ObjectType::{{type.name.CamelCase()}}: {
                    auto* data = {{type.name.CamelCase()}}Objects().Get(objectId);
                    if (data == nullptr) {
                        return false;
                    }
                    if (data->deviceInfo != nullptr) {
                        if (!UntrackDeviceChild(data->deviceInfo, objectType, objectId)) {
                            return false;
                        }
                    }
                    if (data->state == AllocationState::Allocated) {
                        ASSERT(data->handle != nullptr);
                        {% if type.name.CamelCase() in server_reverse_lookup_objects %}
                            {{type.name.CamelCase()}}ObjectIdTable().Remove(data->handle);
                        {% endif %}

                        {% if type.name.get() == "device" %}
                            //* TODO(crbug.com/dawn/384): This is a hack to make sure that all child objects
                            //* are destroyed before their device. We should have a solution in
                            //* Dawn native that makes all child objects internally null if their
                            //* Device is destroyed.
                            while (data->info->childObjectTypesAndIds.size() > 0) {
                                auto [childObjectType, childObjectId] = UnpackObjectTypeAndId(
                                    *data->info->childObjectTypesAndIds.begin());
                                if (!DoDestroyObject(childObjectType, childObjectId)) {
                                    return false;
                                }
                            }
                            if (data->handle != nullptr) {
                                //* Deregisters uncaptured error and device lost callbacks since
                                //* they should not be forwarded if the device no longer exists on the wire.
                                ClearDeviceCallbacks(data->handle);
                            }
                        {% endif %}

                        mProcs.{{as_varName(type.name, Name("release"))}}(data->handle);
                    }
                    {{type.name.CamelCase()}}Objects().Free(objectId);
                    return true;
                }
            {% endfor %}
            default:
                return false;
        }
    }

}  // namespace dawn::wire::server
