 #pragma once
 #include "mof/Vector2D.hpp"
 #include "mof/stream/Manipulator.hpp"
 #include <map>
 #include <algorithm>
 
 namespace mof{
 
 	template <typename T>
 	T stepInterpolate(const std::map<mof::FrameNumber , T>& map , mof::FrameNumber current ){
 		if(map.empty())throw std::invalid_argument("the map is empty");
 		for(
			typename std::map<mof::FrameNumber , T>::const_reverse_iterator itr = map.rbegin() ;
			itr != map.rend() ; 
			++itr
		){
 			if(itr->first <= current)return itr->second;
 		}
 		return map.begin()->second;//default
 	}
  
 	template<class T> inline
 	T calcLinerInterpolationValue( float blending , const T& prevObj , const T& nextObj){
 		return (1 - blending) * prevObj + blending * nextObj;
 	}	
   
    //誤差低減のための特殊化
    /*template<> inline
 	Vector2D calcLinerInterpolationValue( float blending , const Vector2D& prev , const Vector2D& next )
    {
 		return mof::Vector2D
        (
             prev.x != next.x ? (1 - blending) * prev.x + blending * next.x : prev.x , 
             prev.y != next.y ? (1 - blending) * prev.y + blending * next.y : prev.y  
        );
 	}*/	

 	template <typename T>
 	T linerInterpolate(const std::map<mof::FrameNumber , T>& map , mof::FrameNumber current ){
 		if(map.empty())throw std::invalid_argument("the map is empty");
 		typename std::map<mof::FrameNumber , T>::const_iterator n = map.find(current);
 		if(n != map.end())return n->second;// just key frame
 		
 		//直前、直後のキーを検索
 		mof::FrameNumber prevKeyFrame = current;
 		bool foundPrev = false;
 		T prevObj;
 		mof::FrameNumber nextKeyFrame = current;
 		bool foundNext = false;
 		T nextObj;
 		
 		for(
				typename std::map<mof::FrameNumber , T>::const_iterator itr = map.begin() ;
				itr != map.end() ;
				++itr
			){
 			if(itr->first < current && (!foundPrev || itr->first > prevKeyFrame)){
 				foundPrev = true;
 				prevKeyFrame = itr->first;
 				prevObj = itr->second;
 			}
 			else if(itr->first > current && (!foundNext || itr->first < nextKeyFrame)){
 				foundNext = true;
 				nextKeyFrame = itr->first;
 				nextObj = itr->second;
 			}
 			
 		}
 		
 		assert(foundPrev || foundNext);
 		if(!foundPrev && foundNext)return nextObj;//直前のキーは見つからなかった
 		else if(foundPrev && !foundNext)return prevObj;//直後のキーは見つからなかった
 		float blending = static_cast<float>(current - prevKeyFrame) / static_cast<float>(nextKeyFrame - prevKeyFrame);
 		return calcLinerInterpolationValue<T>(blending , prevObj ,  nextObj);
 	}
 
 } //namespace mof
 
 
