#ifndef _WRITE_COPY_HPP_
#define  _WRITE_COPY_HPP_
//add之前如果有数据，需要把运行中更改的数据进行保存。
#include <unordered_map>
#include <algorithm>
#include <memory>
#include <mutex>
#include <atomic>
#include "visit.h"

template<typename T,typename K,typename V> 
struct write_copy_base:acceptor<V>
{
	void accept(visitor<V> &v)
	{
		for(std::pair<K,V> me:m_map)
		{
			v.visit(me.second);
		}
	}

	std::unordered_map<K,V> m_map;
	int m_version=0;
	write_copy_base()
	{}

	int version()const
	{
		return m_version;
	}

	int set_version(int v)
	{
		return m_version=++v;
	}


	V get(K k)const
	{
		return m_map[k];
	}

	V get(K k)
	{
		auto serch = m_map.find(k);
		if(serch != m_map.end())
		  return serch->second;
		else
		  return nullptr;
	}

	std::shared_ptr<T> clone()const
	{
		std::shared_ptr<T> ret=std::make_shared<T>();
		ret->m_map.insert(m_map.begin(),m_map.end());
		ret->set_version(m_version);

		return ret;
	}

	std::shared_ptr<T> clone_add(const std::unordered_map<K,V>&m)const
	{
		std::shared_ptr<T> ret=std::move(clone());
		ret->_add(m);
		return ret;
	}

	std::shared_ptr<T> clone_add(K k,V v)const
	{
		std::shared_ptr<T> ret=std::move(clone());
		ret->_add(k,v);
		return ret;
	}

	std::shared_ptr<T> clone_remove(K k)const
	{
		std::shared_ptr<T> ret=std::move(clone());
		ret->_remove(k);
		return ret;
	}

	std::shared_ptr<T> clone_remove(const std::vector<K>&list)const
	{
		std::shared_ptr<T> ret=std::move(clone());
		ret->_remove(list);
		return ret;
	}

	virtual ~write_copy_base()
	{
//		std::for_each(m_list.begin(),m_list.end(),[](K*it){ });
	}
private:
	void _remove(K k)
	{
		m_map.erase(k);
	}

	void _remove(const std::vector<K>& v)
	{
        for(K k:v)
		{
			m_map.erase(k);
		}
	}

	void _add(K k,V v)
	{
		m_map.insert(std::make_pair(k,v));
	}

	void _add(const std::unordered_map<K,V>&m)
	{
		m_map.insert(m.begin(),m.end());
	}
};

template<typename T,typename K,typename V>
struct single_base:write_copy_base<T,K,V>
{
	typedef write_copy_base<T,K,V> base;
	static std::shared_ptr<T> m_instance;
	static std::shared_ptr<T> instance()
	{
		return m_instance;
	}

	std::mutex m_mutex;

	void add(K k,V c)
	{
		std::lock_guard<std::mutex> lock(m_mutex);
		m_instance=std::move(base::clone_add(k,c));
	}

	void add(const std::unordered_map<K,V>&c)
	{
		std::lock_guard<std::mutex> lock(m_mutex);
		m_instance=std::move(base::clone_add(c));
	}
	void remove(K k,V c)
	{
		std::lock_guard<std::mutex> lock(m_mutex);
		m_instance=std::move(base::clone_remove(k,c));
	}

	void remove(const std::unordered_map<K,V>&c)
	{
		std::lock_guard<std::mutex> lock(m_mutex);
		m_instance=std::move(base::clone_remove(c));
	}

    void remove(const std::vector<K>&list)
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_instance=std::move(base::clone_remove(list));
    }

    void remove(K k)
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_instance=std::move(base::clone_remove(k));
    }
};

#endif


