/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
 * Copyright 2008-2010 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#ifndef OSGEARTH_REVISIONING_H
#define OSGEARTH_REVISIONING_H 1

#include <osgEarth/Common>

namespace osgEarth
{
    /**
     * A tracking revision. See "class Revisioned" below for details.
     */
    struct Revision // header-only; no export
    {
        Revision() : _value(-1) { }
        Revision(int init) : _value(init) { }
        void reset() { _value = -1; }
        operator int() const { return _value; }
        int operator ++() { return ++_value; }
        int operator --() { return --_value; }
    private:
        int _value;
    };

    /**
     * Base class for a revisioned object. A Revisioned object is one that keeps track
     * of its state with a version number. Other objects can then hold a Revision object
     * (see above) and use it to see if they are up to date with this object, thereby
     * enabling passive data model synchronization.
     */
    template<typename T> class Revisioned : public T // header-only; no export
    {
    public:
        /** Marks this object as dirty */
        void dirty() {
            ++_revision;
        }

        /** Synchronizes the external revision number with this revision, effectively
            bringing the external object up to date. */
        virtual void sync( Revision& externalRevision ) const {
            externalRevision = _revision;
        }

        /** Returns true if the external object is at a different revision that this object. */
        bool outOfSyncWith( const Revision& externalRevision) const {
            return !inSyncWith( externalRevision );
        }

        /** Returns true if the external object is at the same revision as this object. */
        virtual bool inSyncWith( const Revision& externalRevision ) const {
            return _alwaysDirty ? false : _revision == externalRevision;
        }

    protected:
        Revisioned() : _revision(0), _alwaysDirty(false) { }

        /** Marks this object as always being dirty (i.e. inSyncWith() will always return false) */
        void setAlwaysDirty( bool value ) {
            _alwaysDirty = value;
        }

    private:
        Revision _revision;
        bool _alwaysDirty;
    };
}

#endif // OSGEARTH_REVISIONING_H
