/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkTScopedComPtr_DEFINED
#define SkTScopedComPtr_DEFINED

#include "SkLeanWindows.h"

#ifdef SK_BUILD_FOR_WIN

template<typename T>
class SkBlockComRef : public T {
private:
    virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
    virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
    virtual ~SkBlockComRef() {}
};

template<typename T> T* SkRefComPtr(T* ptr) {
    ptr->AddRef();
    return ptr;
}

template<typename T> T* SkSafeRefComPtr(T* ptr) {
    if (ptr) {
        ptr->AddRef();
    }
    return ptr;
}

template<typename T>
class SkTScopedComPtr {
private:
    T *fPtr;

public:
    constexpr SkTScopedComPtr() : fPtr(nullptr) {}
    constexpr SkTScopedComPtr(std::nullptr_t) : fPtr(nullptr) {}
    explicit SkTScopedComPtr(T *ptr) : fPtr(ptr) {}
    SkTScopedComPtr(SkTScopedComPtr&& that) : fPtr(that.release()) {}
    SkTScopedComPtr(const SkTScopedComPtr&) = delete;

    ~SkTScopedComPtr() { this->reset();}

    SkTScopedComPtr& operator=(SkTScopedComPtr&& that) {
        this->reset(that.release());
        return *this;
    }
    SkTScopedComPtr& operator=(const SkTScopedComPtr&) = delete;
    SkTScopedComPtr& operator=(std::nullptr_t) { this->reset(); return *this; }

    T &operator*() const { SkASSERT(fPtr != nullptr); return *fPtr; }

    explicit operator bool() const { return fPtr != nullptr; }

    SkBlockComRef<T> *operator->() const { return static_cast<SkBlockComRef<T>*>(fPtr); }

    /**
     * Returns the address of the underlying pointer.
     * This is dangerous -- it breaks encapsulation and the reference escapes.
     * Must only be used on instances currently pointing to NULL,
     * and only to initialize the instance.
     */
    T **operator&() { SkASSERT(fPtr == nullptr); return &fPtr; }

    T *get() const { return fPtr; }

    void reset(T* ptr = nullptr) {
        if (fPtr) {
            fPtr->Release();
        }
        fPtr = ptr;
    }

    void swap(SkTScopedComPtr<T>& that) {
        T* temp = this->fPtr;
        this->fPtr = that.fPtr;
        that.fPtr = temp;
    }

    T* release() {
        T* temp = this->fPtr;
        this->fPtr = nullptr;
        return temp;
    }
};

#endif  // SK_BUILD_FOR_WIN
#endif  // SkTScopedComPtr_DEFINED
