/*-----------------------------------------------------------------------------

Copyright (C) 2012

A. Ronald Gallant
Post Office Box 659 
Chapel Hill NC 27514 
USA   

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

-----------------------------------------------------------------------------*/

// For flagmap documentation read flagmap.h and frontend.cpp in that order.

// DEBUG_PLAY is set true in makefile.dbg and false in makefile

#include "libscl.h"
#include "flagmap.h"
#include "craps.h"

using namespace scl;
using namespace std;
using namespace craps;
using namespace flagmap;

#if defined DEBUG_PLAY
  #include "debug_play.h"
  #include "debug_play_0.inc"
#endif

namespace flagmap {
  void define_flag(std::map<std::string,flagmap::fval>& flag)
  {
    flag["filenames_expected"] = fval("");
    flag["filenames_expected"].set = true;

    flag["h"]    = fval("-h  help message"); 
    flag["p"]    = fval("-p  value     number of players",'i');
    flag["r"]    = fval("-r  value     number of rolls",'i');
    flag["s"]    = fval("-s  filename  strategies, one line per player",'s');
    flag["o"]    = fval("-o  filename  override default output filename",'s');
  }

  istream& process_filename(istream& fin,
      std::string progname,
      std::map<std::string,flagmap::fval> flag,
      std::vector<std::string> file)
  {
    return process_filename_example(fin,progname,flag,file);
  }
}


int main(int argc, char** argp, char** envp)
{
  map<std::string,fval> flag;
  vector<std::string> file;
  define_flag(flag);

  INTEGER num_players = 1;
  INTEGER num_rolls = 100;

  vector<string> player_strategies;

  string progname;
  if (flagmap::process_flag(argc, argp, progname, flag, file) != 0) return 1; 

  if (flag["r"].set) num_rolls = flag["r"].i;

  if (flag["p"].set) num_players = flag["p"].i;

  if (flag["s"].set) {
    string filename = (flag["s"].s);
    ifstream fin;
    fin.open(filename.c_str());
    if (fin) {
      string strategy_name;
      while(fin >> strategy_name) player_strategies.push_back(strategy_name);
    }
    else {
      for (INTEGER i=1; i<=num_players; ++i) {
        player_strategies.push_back("pass_line_only");
      }
    }
  }       
  
  strategy_list available_strategies;
  
  list<player_t> players(num_players);

  vector<string>::size_type player_number_counter = 0;

  for (list<player_t>::iterator p=players.begin(); p!=players.end(); ++p) {

    vector<string>::size_type n = player_number_counter;

    p -> number = ++player_number_counter;
    p -> stake = 0;
    p -> strategy = available_strategies(player_strategies[n]);
  }
  
  #if defined DEBUG_PLAY
    #include "debug_play_1.inc"
  #endif

  house_t house;
  house.stake = 0;

  marker_t marker;
  roll_t roll;

  INT_32BIT seed = 1001;

  string filename = "play.csv";
  if (flag["o"].set) filename = (flag["o"].s);
  ofstream fout;
  fout.open(filename.c_str());
  if (fout) {
    fout<<"\"player\",\"strategy\",\"bet\",\"wager\",\"payoff\",\"counter\"\n";
  }
  else {
    error("Error, could not open " + filename);
  }

  for (INTEGER counter = 1; counter <= num_rolls; ++counter) {

    #if defined DEBUG_PLAY
      #include "debug_play_2.inc"
    #endif

    for (list<player_t>::iterator p=players.begin(); p!=players.end(); ++p) {
      INTEGER n = p->number;
      strategy_base* sptr = p->strategy;
      payoff_t pay = (*sptr)(roll,marker,n,p->bets);
      house.stake += pay.house;
      p->stake += pay.player;
    }

    #if defined DEBUG_PLAY
      #include "debug_play_3.inc"
    #endif

    INTEGER sum = 0;
    sum += roll.first = iran(seed,5) + 1;
    sum += roll.second = iran(seed,5) + 1;

    #if defined DEBUG_PLAY
      #include "debug_play_4.inc"
    #endif 

    for (list<player_t>::iterator p=players.begin(); p!=players.end(); ++p) {
      bool remove_bet = false;
      list<bet_base*>::iterator bets_itr = p->bets.begin();
      while(bets_itr != p->bets.end()) {
        bet_base* bet_ptr = *bets_itr;  // bets_itr is incremented below
        payoff_t pay = bet_ptr->house_action(roll,marker,remove_bet);
        house.stake += pay.house;
        p->stake += pay.player;
        if (remove_bet) { 
          INTEGER wager = bet_ptr->get_wager();
          fout << "\"player" << fmt('i',2,p->number)('_') << "\","
             << "\"" << p->strategy->get_name() << "\","
             << "\"" << bet_ptr->get_name() << "\","
             << wager << ','
             << pay.player << ','
             << counter << '\n';
          delete bet_ptr;
          bets_itr = p->bets.erase(bets_itr);
        }
        else {
          ++bets_itr;
        }

      }
    }

    #if defined DEBUG_PLAY
      #include "debug_play_3.inc"
    #endif

    marker.marker_action(roll);
  }

}

