
#ifndef _fake_stuff
#define _fake_stuff

#include <fstream>
using namespace std;

#include "Networking/Player.h"

template<class T>
void check_share(vector<T>& Sa, typename T::clear& value,
    typename T::value_type& mac, int N, const typename T::value_type& key);

template<class T> class Share;

template<class T, class V>
void check_share(vector<Share<T> >& Sa,
  V& value,
  T& mac,
  int N,
  const T& key);

// Generate MAC key shares
void generate_keys(const string& directory, int nplayers);

template <class T>
void write_mac_key(const string& directory, int player_num, int nplayers, T key);

template <class U>
void read_mac_key(const string& directory, int player_num, int nplayers, U& key);
template <class U>
void read_mac_key(const string& directory, const Names& N, U& key);

template <class T>
typename T::mac_key_type read_generate_write_mac_key(const Player& P,
        string directory = "");

template <class T>
class Files
{
public:
  ofstream* outf;
  int N;
  typename T::mac_type key;
  PRNG G;
  Files(int N, const typename T::mac_type& key, const string& prefix) : N(N), key(key)
  {
    outf = new ofstream[N];
    for (int i=0; i<N; i++)
      {
        stringstream filename;
        filename << prefix << "-P" << i;
        cout << "Opening " << filename.str() << endl;
        outf[i].open(filename.str().c_str(),ios::out | ios::binary);
        if (outf[i].fail())
          throw file_error(filename.str().c_str());
      }
    G.ReSeed();
  }
  ~Files()
  {
    delete[] outf;
  }
  template<class U = T>
  void output_shares(const typename U::clear& a)
  {
    output_shares<T>(a, key);
  }
  template<class U>
  void output_shares(const typename U::clear& a,
      const typename U::mac_type& key)
  {
    vector<U> Sa(N);
    make_share(Sa,a,N,key,G);
    for (int j=0; j<N; j++)
      Sa[j].output(outf[j],false);
  }
};

#endif
