#pragma once
#include "mof/stream/Manipulator.hpp"
#include <mof/Timer.hpp>

namespace mof{
	void state_changed();
	unsigned long get_global_ts();

    template< typename T >
	class Cache : public Manipulator< T >
    {
			
	public:
        typedef typename std::shared_ptr<Cache> Handler;

        virtual ~Cache( ){}

		virtual T value( FrameNumber frame ) const
        {
			if (local_ts_ < mof::get_global_ts() || m_lastFrame != frame) {
				// キャッシュが無効になっている可能性
				local_ts_ = mof::Timer::getSystemTime();
            	m_lastFrame = frame;
            	m_cached = m_pBody->value(frame);
			}
			return m_cached;
		}

		
    private:
        typename Manipulator<T>::Handler m_pBody;
        mutable FrameNumber m_lastFrame;
        mutable T m_cached;
		mutable unsigned long local_ts_;

		Cache(const typename Manipulator<T>::Handler& pBody)
		: m_pBody(pBody) , m_lastFrame(0), local_ts_(0)
		{
		}

        template<typename T > friend
	    typename std::shared_ptr< Cache<T> > makeCacheHandler
        (
	    	const typename Manipulator<T>::Handler& pBody 
        );

	};



	template< typename T >
	std::shared_ptr< Cache< T > > makeCacheHandler
    (
		const typename Manipulator< T >::Handler& pBody 
    )
    {
		return typename Cache< T >::Handler(
		        new Cache< T >( pBody )
	        );
	}


} //namespace mof

