/*
 * 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 SkTLazy_DEFINED
#define SkTLazy_DEFINED

#include "include/private/base/SkAssert.h"

#include <optional>
#include <utility>

/**
 *  Efficient way to defer allocating/initializing a class until it is needed
 *  (if ever).
 */
template <typename T> class SkTLazy {
public:
    SkTLazy() = default;
    explicit SkTLazy(const T* src) : fValue(src ? std::optional<T>(*src) : std::nullopt) {}
    SkTLazy(const SkTLazy& that) : fValue(that.fValue) {}
    SkTLazy(SkTLazy&& that) : fValue(std::move(that.fValue)) {}

    ~SkTLazy() = default;

    SkTLazy& operator=(const SkTLazy& that) {
        fValue = that.fValue;
        return *this;
    }

    SkTLazy& operator=(SkTLazy&& that) {
        fValue = std::move(that.fValue);
        return *this;
    }

    /**
     *  Return a pointer to an instance of the class initialized with 'args'.
     *  If a previous instance had been initialized (either from init() or
     *  set()) it will first be destroyed, so that a freshly initialized
     *  instance is always returned.
     */
    template <typename... Args> T* init(Args&&... args) {
        fValue.emplace(std::forward<Args>(args)...);
        return this->get();
    }

    /**
     *  Copy src into this, and return a pointer to a copy of it. Note this
     *  will always return the same pointer, so if it is called on a lazy that
     *  has already been initialized, then this will copy over the previous
     *  contents.
     */
    T* set(const T& src) {
        fValue = src;
        return this->get();
    }

    T* set(T&& src) {
        fValue = std::move(src);
        return this->get();
    }

    /**
     * Destroy the lazy object (if it was created via init() or set())
     */
    void reset() {
        fValue.reset();
    }

    /**
     *  Returns true if a valid object has been initialized in the SkTLazy,
     *  false otherwise.
     */
    bool isValid() const { return fValue.has_value(); }

    /**
     * Returns the object. This version should only be called when the caller
     * knows that the object has been initialized.
     */
    T* get() {
        SkASSERT(fValue.has_value());
        return &fValue.value();
    }
    const T* get() const {
        SkASSERT(fValue.has_value());
        return &fValue.value();
    }

    T* operator->() { return this->get(); }
    const T* operator->() const { return this->get(); }

    T& operator*() {
        SkASSERT(fValue.has_value());
        return *fValue;
    }
    const T& operator*() const {
        SkASSERT(fValue.has_value());
        return *fValue;
    }

    /**
     * Like above but doesn't assert if object isn't initialized (in which case
     * nullptr is returned).
     */
    const T* getMaybeNull() const { return fValue.has_value() ? this->get() : nullptr; }
          T* getMaybeNull()       { return fValue.has_value() ? this->get() : nullptr; }

private:
    std::optional<T> fValue;
};

/**
 * A helper built on top of std::optional to do copy-on-first-write. The object is initialized
 * with a const pointer but provides a non-const pointer accessor. The first time the
 * accessor is called (if ever) the object is cloned.
 *
 * In the following example at most one copy of constThing is made:
 *
 * SkTCopyOnFirstWrite<Thing> thing(&constThing);
 * ...
 * function_that_takes_a_const_thing_ptr(thing); // constThing is passed
 * ...
 * if (need_to_modify_thing()) {
 *    thing.writable()->modifyMe(); // makes a copy of constThing
 * }
 * ...
 * x = thing->readSomething();
 * ...
 * if (need_to_modify_thing_now()) {
 *    thing.writable()->changeMe(); // makes a copy of constThing if we didn't call modifyMe()
 * }
 *
 * consume_a_thing(thing); // could be constThing or a modified copy.
 */
template <typename T>
class SkTCopyOnFirstWrite {
public:
    explicit SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}

    explicit SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}

    // Constructor for delayed initialization.
    SkTCopyOnFirstWrite() : fObj(nullptr) {}

    SkTCopyOnFirstWrite(const SkTCopyOnFirstWrite&  that) { *this = that;            }
    SkTCopyOnFirstWrite(      SkTCopyOnFirstWrite&& that) { *this = std::move(that); }

    SkTCopyOnFirstWrite& operator=(const SkTCopyOnFirstWrite& that) {
        fLazy = that.fLazy;
        fObj  = fLazy.has_value() ? &fLazy.value() : that.fObj;
        return *this;
    }

    SkTCopyOnFirstWrite& operator=(SkTCopyOnFirstWrite&& that) {
        fLazy = std::move(that.fLazy);
        fObj  = fLazy.has_value() ? &fLazy.value() : that.fObj;
        return *this;
    }

    // Should only be called once, and only if the default constructor was used.
    void init(const T& initial) {
        SkASSERT(!fObj);
        SkASSERT(!fLazy.has_value());
        fObj = &initial;
    }

    // If not already initialized, in-place instantiates the writable object
    template <typename... Args>
    void initIfNeeded(Args&&... args) {
        if (!fObj) {
            SkASSERT(!fLazy.has_value());
            fObj = &fLazy.emplace(std::forward<Args>(args)...);
        }
    }

    /**
     * Returns a writable T*. The first time this is called the initial object is cloned.
     */
    T* writable() {
        SkASSERT(fObj);
        if (!fLazy.has_value()) {
            fLazy = *fObj;
            fObj = &fLazy.value();
        }
        return &fLazy.value();
    }

    const T* get() const { return fObj; }

    /**
     * Operators for treating this as though it were a const pointer.
     */

    const T *operator->() const { return fObj; }

    operator const T*() const { return fObj; }

    const T& operator *() const { return *fObj; }

private:
    const T*         fObj;
    std::optional<T> fLazy;
};

#endif
