/*
 * 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/core/SkTypes.h"
#include <optional>

/**
 *  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
