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

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

/**
 * A helper built on top of SkTLazy 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.isValid() ? fLazy.get() : that.fObj;
        return *this;
    }

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

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

    // If not already initialized, in-place instantiates the writable object
    template <typename... Args>
    void initIfNeeded(Args&&... args) {
        if (nullptr == fObj) {
            SkASSERT(!fLazy.isValid());
            fObj = fLazy.init(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.isValid()) {
            fLazy.set(*fObj);
            fObj = fLazy.get();
        }
        return const_cast<T*>(fObj);
    }

    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;
    SkTLazy<T>  fLazy;
};

#endif
