/* osgEarth
* Copyright 2025 Pelican Mapping
* MIT License
*/

#ifndef OSGEARTH_STATUS_H
#define OSGEARTH_STATUS_H 1

#include <osgEarth/Common>
#include <string>

namespace osgEarth
{
    /** General purpose status object */
    class OSGEARTH_EXPORT Status
    {
    public:
        enum Code {
            NoError,
            ResourceUnavailable,  // e.g. failure to access a file, URL, database, or other resource
            ServiceUnavailable,   // e.g. failure to load a plugin, extension, or other module
            ConfigurationError,   // required data or properties missing
            AssertionFailure,     // an illegal software state was detected
            GeneralError          // something else went wrong
        };

    public:
        Status() : _code(NoError) { }
        Status(const Status& rhs) : _code(rhs._code), _msg(rhs._msg) { }
        Status(const Code& code) : _code(code) { }
        Status(const std::string& msg) : _code(GeneralError), _msg(msg) { }
        Status(const Code& code, const std::string& msg) : _code(code), _msg(msg) { }
        bool isOK() const { return _code == NoError; }
        bool isError() const { return !isOK(); }
        const Code& code() const { return _code; }
        const std::string& message() const { return _msg; }
        bool operator == (const Status& rhs) const { return _code == rhs._code && _msg.compare(rhs._msg) == 0; }
        bool operator != (const Status& rhs) const { return !(*this==rhs); }
        bool const operator ! () const { return isError(); }
        static Status OK() { return Status(); }
        static Status Error(const Code& code) { return Status(code); }
        static Status Error(const std::string& msg) { return Status(msg); }
        static Status Error(const Code& code, const std::string& msg) { return Status(code, msg); }
        void set(const Code& code) { _code = code, _msg = ""; }
        void set(const Code& code, const std::string& msg) { _code = code, _msg = msg; }
        std::string toString() const {
            return _codeText[(unsigned)_code < 6 ? (int)_code : 5] + ": " + message();
        }
    private:
        Code _code;
        std::string _msg;
        static std::string _codeText[6];
    };

    extern OSGEARTH_EXPORT const Status STATUS_OK;

    /**
     * Generic return value that wraps a value type and a Status.
     */
    template<typename T>
    class Result : public Status
    {
    public:
        Result() : Status() { }
        Result(const T& val) : _value(val) { }
        Result(const Status& s) : Status(s) { }
        const T& value() const { return _value; }
        const T& get() const { return _value; }
        const T* operator -> () const { return &_value; }
    private:
        T _value;
    };
}

#define OE_RETURN_STATUS_ON_ERROR(F) \
    { osgEarth::Status s = F; if (s.isError()) return s; }

#endif // OSGEARTH_STATUS_H
