/************************************************************************
    MeOS - Orienteering Software
    Copyright (C) 2009-2011 Melin Software HB
    
    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 3 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, see <http://www.gnu.org/licenses/>.

    Melin Software HB - software@melin.nu - www.melin.nu
    Stigbergsvägen 7, SE-75242 UPPSALA, Sweden
    
************************************************************************/

#include "stdafx.h"

#include <vector>
#include <set>
#include <cassert>
#include <algorithm>

#include "oEvent.h"
#include "gdioutput.h"
#include "oDataContainer.h"

#include "random.h"
#include "SportIdent.h"

#include "oFreeImport.h"

#include "meos.h"
#include "meos_util.h"
#include "RunnerDB.h"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>

#include "Localizer.h"


void oEvent::generateCompetitionReport(gdioutput &gdi)
{
  gdi.fillDown();
  gdi.addString("", boldLarge, "Tävlingsstatistik");

  
  int lh = gdi.getLineHeight();

  oClassList::iterator it;
  
  reinitializeClasses();
  Classes.sort();

  gdi.dropLine();
 //  int xp = gdi.getCX();
//  int yp = gdi.getCY();
  int entries=0;
  int started=0;
  int fee=0;
//  int dx[]={0, 150, 200, 250, 350, 450};

  int entries_sum=0;
  int started_sum=0;
  int fee_sum=0;

  int entries_sum_y=0;
  int started_sum_y=0;
  int fee_sum_y=0;

  int cfee;
  gdi.addString("", boldText, "Elitklasser");
  vector<string> types;
  types.push_back(lang.tl(oClass::ctypeElit));
  cfee = getDCI().getInt("EliteFee");
  generateStatisticsPart(gdi, types, 0, cfee, 90, entries, started, fee);
  entries_sum += entries;
  started_sum +=  started;
  fee_sum += fee;

  gdi.addString("", boldText, "Vuxenklasser");
  types.clear();
  types.push_back(lang.tl(oClass::ctypeMain));
  types.push_back(lang.tl(oClass::ctypeMotion));
  cfee = getDCI().getInt("EntryFee");
  generateStatisticsPart(gdi, types, 0, cfee, 90, entries, started, fee);
  entries_sum += entries;
  started_sum +=  started;
  fee_sum += fee;

  gdi.addString("", boldText, "Ungdomsklasser");
  types.clear();
  types.push_back(lang.tl(oClass::ctypeYouth));
  cfee = getDCI().getInt("YouthFee");
  generateStatisticsPart(gdi, types, 0, cfee, 50, entries, started, fee);
  entries_sum_y += entries;
  started_sum_y +=  started;
  fee_sum_y += fee;

  types.clear();
  types.push_back(lang.tl(oClass::ctypeOpen));
  
  gdi.addString("", boldText, "Öppna klasser, vuxna");
  cfee = getDCI().getInt("EntryFee");
  generateStatisticsPart(gdi, types, cfee, cfee, 90, entries, started, fee);
  entries_sum += entries;
  started_sum +=  started;
  fee_sum += fee;

  gdi.addString("", boldText, "Öppna klasser, ungdom");
  cfee = getDCI().getInt("YouthFee");
  generateStatisticsPart(gdi, types, cfee, cfee, 50, entries, started, fee);
  entries_sum_y += entries;
  started_sum_y +=  started;
  fee_sum_y += fee;

  gdi.addString("", boldText, "Sammanställning");
  gdi.dropLine();
  int xp = gdi.getCX();
  int yp = gdi.getCY();

  gdi.addString("", yp, xp+200, textRight|fontMedium, "Vuxna");
  gdi.addString("", yp, xp+300, textRight|fontMedium, "Ungdom");
  gdi.addString("", yp, xp+400, textRight|fontMedium, "Totalt");

  yp+=lh;
  gdi.addString("", yp, xp+0, fontMedium, "Anmälda");
  gdi.addStringUT(yp, xp+200, textRight|fontMedium, itos(entries_sum));
  gdi.addStringUT(yp, xp+300, textRight|fontMedium, itos(entries_sum_y));
  gdi.addStringUT(yp, xp+400, textRight|boldText, itos(entries_sum+entries_sum_y));

  yp+=lh;
  gdi.addString("", yp, xp+0, fontMedium, "Startande");
  gdi.addStringUT(yp, xp+200, textRight|fontMedium, itos(started_sum));
  gdi.addStringUT(yp, xp+300, textRight|fontMedium, itos(started_sum_y));
  gdi.addStringUT( yp, xp+400, textRight|boldText, itos(started_sum+started_sum_y));

  yp+=lh;
  gdi.addString("", yp, xp+0, fontMedium, "Grundavgift");
  gdi.addStringUT(yp, xp+200, textRight|fontMedium, itos(fee_sum));
  gdi.addStringUT(yp, xp+300, textRight|fontMedium, itos(fee_sum_y));
  gdi.addStringUT(yp, xp+400, textRight|boldText, itos(fee_sum+fee_sum_y));

  yp+=lh;
  gdi.addString("", yp, xp+0, fontMedium, "SOFT-avgift");
  gdi.addStringUT(yp, xp+200, textRight|fontMedium, itos(entries_sum*15));
  gdi.addStringUT(yp, xp+300, textRight|fontMedium, itos(entries_sum_y*5));
  gdi.addStringUT(yp, xp+400, textRight|boldText, itos(entries_sum*15+entries_sum_y*5));

  yp+=lh*2;
  gdi.addString("", yp, xp+0,fontMedium, "Underlag för tävlingsavgift:");
  int baseFee =  (fee_sum+fee_sum_y) - (entries_sum*15+5*entries_sum_y);
  gdi.addStringUT(yp, xp+200,fontMedium, itos(baseFee));

  yp+=lh;
  gdi.addString("", yp, xp+0,fontMedium, "Total tävlingsavgift:");
  int cmpFee =  int((baseFee * .34 * (baseFee - 5800)) / (200000));  
  gdi.addStringUT(yp, xp+200, fontMedium, itos(cmpFee));

  yp+=lh;
  gdi.addString("", yp, xp, fontMedium, "Avrundad tävlingsavgift:");
  gdi.addStringUT(yp, xp+200, boldText, itos(((cmpFee+50))/100)+"00");

  gdi.dropLine();
  gdi.addString("", boldText, "Geografisk fördelning");
  gdi.addString("", fontSmall, "Anmälda per distrikt");
  gdi.dropLine(0.2);
  yp = gdi.getCY();
  vector<int> runners;
  vector<string> districts;
  getRunnersPerDistrict(runners);
  getDistricts(districts);
  int nd = min(runners.size(), districts.size());
  
  int ybase = yp;
  for (int k=1;k<=nd;k++) {
    gdi.addStringUT(yp, xp, fontMedium, itos(k) + " " + districts[k%nd]);
    gdi.addStringUT(yp, xp+200, textRight|fontMedium, itos(runners[k%nd]));
    yp+=lh;
    if (k%8==0){
      yp = ybase;
      xp += 250;
    }
  } 
}

void oEvent::generateStatisticsPart(gdioutput &gdi, const vector<string> &type, int feeLock, 
                                    int actualFee, int baseFee, 
                                    int &entries_sum, int &started_sum, int &fee_sum) const
{
  entries_sum=0;
  started_sum=0;
  fee_sum=0;
  int xp = gdi.getCX();
  int yp = gdi.getCY();
  int entries;
  int started;
  int dx[]={0, 150, 210, 270, 350, 450};
  int lh = gdi.getLineHeight();
  oClassList::const_iterator it;

  gdi.addString("", yp, xp+dx[0], fontSmall, "Klass");
  gdi.addString("", yp, xp+dx[1], textRight|fontSmall, "Anm. avg.");
  gdi.addString("", yp, xp+dx[2], textRight|fontSmall, "Grund avg.");
  gdi.addString("", yp, xp+dx[3], textRight|fontSmall, "Anmälda");
  gdi.addString("", yp, xp+dx[4], textRight|fontSmall, "Avgift");
  gdi.addString("", yp, xp+dx[5], textRight|fontSmall, "Startande");
  yp+=lh;
  for(it=Classes.begin(); it!=Classes.end(); ++it) {
    if (it->isRemoved())
      continue;
    if (count(type.begin(), type.end(), it->getType())==1) {
      it->getStatistics(feeLock, entries, started);
      gdi.addStringUT(yp, xp+dx[0], fontMedium, it->getName());
      gdi.addStringUT(yp, xp+dx[1], textRight|fontMedium, itos(actualFee));
      gdi.addStringUT(yp, xp+dx[2], textRight|fontMedium, itos(baseFee));
      gdi.addStringUT(yp, xp+dx[3], textRight|fontMedium, itos(entries));
      gdi.addStringUT(yp, xp+dx[4], textRight|fontMedium, itos(baseFee*entries));
      gdi.addStringUT(yp, xp+dx[5], textRight|fontMedium, itos(started));
      entries_sum += entries;
      started_sum += started;
      fee_sum += entries*baseFee;
      yp+=lh;
    }
  }
  yp+=lh/2;
  gdi.addStringUT(yp, xp+dx[3], textRight|boldText, itos(entries_sum));
  gdi.addStringUT(yp, xp+dx[4], textRight|boldText, itos(fee_sum));
  gdi.addStringUT(yp, xp+dx[5], textRight|boldText, itos(started_sum));
  gdi.dropLine();
}

void oEvent::getRunnersPerDistrict(vector<int> &runners) const
{
  runners.clear();
  runners.resize(24);

  oRunnerList::const_iterator it;

  for (it = Runners.begin(); it != Runners.end(); ++it) {
    if(!it->skip()) {
      int code = 0;
      if (it->Club) 
        code = it->Club->getDCI().getInt("District");

      if (code>0 && code<24)
        ++runners[code];
      else
        ++runners[0];
    }
  }
}

void oEvent::getDistricts(vector<string> &districts) 
{
  districts.resize(24);
  int i=0;
  districts[i++]="Övriga";
  districts[i++]="Blekinge";
  districts[i++]="Bohuslän-Dal";
  districts[i++]="Dalarna";
  districts[i++]="Gotland";
  districts[i++]="Gästrikland";
  districts[i++]="Göteborg";
  districts[i++]="Halland";
  districts[i++]="Hälsingland";
  districts[i++]="Jämtland-Härjedalan";
  districts[i++]="Medelpad";
  districts[i++]="Norrbotten";
  districts[i++]="Örebro län";
  districts[i++]="Skåne";
  districts[i++]="Småland";
  districts[i++]="Stockholm";
  districts[i++]="Södermanland";
  districts[i++]="Uppland";
  districts[i++]="Värmland";
  districts[i++]="Västerbotten";
  districts[i++]="Västergötland";
  districts[i++]="Västmanland";
  districts[i++]="Ångermanland";
  districts[i++]="Östergötland";
}
