// Copyright 2020 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 "dawn_native/Surface.h"

#include "common/Platform.h"
#include "dawn_native/Instance.h"

#if defined(DAWN_PLATFORM_WINDOWS)
#    include "common/windows_with_undefs.h"
#endif  // DAWN_PLATFORM_WINDOWS

#if defined(DAWN_USE_X11)
#    include "common/xlib_with_undefs.h"
#endif  // defined(DAWN_USE_X11)

namespace dawn_native {

#if defined(DAWN_ENABLE_BACKEND_METAL)
    bool InheritsFromCAMetalLayer(void* obj);
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)

    MaybeError ValidateSurfaceDescriptor(const InstanceBase* instance,
                                         const SurfaceDescriptor* descriptor) {
        // TODO(cwallez@chromium.org): Have some type of helper to iterate over all the chained
        // structures.
        if (descriptor->nextInChain == nullptr) {
            return DAWN_VALIDATION_ERROR("Surface cannot be created with just the base descriptor");
        }

        const ChainedStruct* chainedDescriptor = descriptor->nextInChain;
        if (chainedDescriptor->nextInChain != nullptr) {
            return DAWN_VALIDATION_ERROR("Cannot specify two windows for a single surface");
        }

        switch (chainedDescriptor->sType) {
#if defined(DAWN_ENABLE_BACKEND_METAL)
            case wgpu::SType::SurfaceDescriptorFromMetalLayer: {
                const SurfaceDescriptorFromMetalLayer* metalDesc =
                    static_cast<const SurfaceDescriptorFromMetalLayer*>(chainedDescriptor);

                // Check that the layer is a CAMetalLayer (or a derived class).
                if (!InheritsFromCAMetalLayer(metalDesc->layer)) {
                    return DAWN_VALIDATION_ERROR("layer must be a CAMetalLayer");
                }
            } break;
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)

#if defined(DAWN_PLATFORM_WINDOWS)
            case wgpu::SType::SurfaceDescriptorFromWindowsHWND: {
                const SurfaceDescriptorFromWindowsHWND* hwndDesc =
                    static_cast<const SurfaceDescriptorFromWindowsHWND*>(chainedDescriptor);

                // It is not possible to validate an HINSTANCE.

                // Validate the hwnd using the windows.h IsWindow function.
                if (IsWindow(static_cast<HWND>(hwndDesc->hwnd)) == 0) {
                    return DAWN_VALIDATION_ERROR("Invalid HWND");
                }
            } break;
#endif  // defined(DAWN_PLATFORM_WINDOWS)

#if defined(DAWN_USE_X11)
            case wgpu::SType::SurfaceDescriptorFromXlib: {
                const SurfaceDescriptorFromXlib* xDesc =
                    static_cast<const SurfaceDescriptorFromXlib*>(chainedDescriptor);

                // It is not possible to validate an X Display.

                // Check the validity of the window by calling a getter function on the window that
                // returns a status code. If the window is bad the call return a status of zero. We
                // need to set a temporary X11 error handler while doing this because the default
                // X11 error handler exits the program on any error.
                XErrorHandler oldErrorHandler =
                    XSetErrorHandler([](Display*, XErrorEvent*) { return 0; });
                XWindowAttributes attributes;
                int status = XGetWindowAttributes(reinterpret_cast<Display*>(xDesc->display),
                                                  xDesc->window, &attributes);
                XSetErrorHandler(oldErrorHandler);

                if (status == 0) {
                    return DAWN_VALIDATION_ERROR("Invalid X Window");
                }
            } break;
#endif  // defined(DAWN_USE_X11)

            case wgpu::SType::SurfaceDescriptorFromHTMLCanvasId:
            default:
                return DAWN_VALIDATION_ERROR("Unsupported sType");
        }

        return {};
    }

    Surface::Surface(InstanceBase* instance, const SurfaceDescriptor* descriptor)
        : mInstance(instance) {
        ASSERT(descriptor->nextInChain != nullptr);
        const ChainedStruct* chainedDescriptor = descriptor->nextInChain;

        switch (chainedDescriptor->sType) {
            case wgpu::SType::SurfaceDescriptorFromMetalLayer: {
                const SurfaceDescriptorFromMetalLayer* metalDesc =
                    static_cast<const SurfaceDescriptorFromMetalLayer*>(chainedDescriptor);
                mType = Type::MetalLayer;
                mMetalLayer = metalDesc->layer;
            } break;

            case wgpu::SType::SurfaceDescriptorFromWindowsHWND: {
                const SurfaceDescriptorFromWindowsHWND* hwndDesc =
                    static_cast<const SurfaceDescriptorFromWindowsHWND*>(chainedDescriptor);
                mType = Type::WindowsHWND;
                mHInstance = hwndDesc->hinstance;
                mHWND = hwndDesc->hwnd;
            } break;

            case wgpu::SType::SurfaceDescriptorFromXlib: {
                const SurfaceDescriptorFromXlib* xDesc =
                    static_cast<const SurfaceDescriptorFromXlib*>(chainedDescriptor);
                mType = Type::Xlib;
                mXDisplay = xDesc->display;
                mXWindow = xDesc->window;
            } break;

            default:
                UNREACHABLE();
        }
    }

    Surface::~Surface() = default;

    InstanceBase* Surface::GetInstance() {
        return mInstance.Get();
    }

    Surface::Type Surface::GetType() const {
        return mType;
    }

    void* Surface::GetMetalLayer() const {
        ASSERT(mType == Type::MetalLayer);
        return mMetalLayer;
    }

    void* Surface::GetHInstance() const {
        ASSERT(mType == Type::WindowsHWND);
        return mHInstance;
    }
    void* Surface::GetHWND() const {
        ASSERT(mType == Type::WindowsHWND);
        return mHWND;
    }

    void* Surface::GetXDisplay() const {
        ASSERT(mType == Type::Xlib);
        return mXDisplay;
    }
    uint32_t Surface::GetXWindow() const {
        ASSERT(mType == Type::Xlib);
        return mXWindow;
    }

}  // namespace dawn_native
