#include "combo.h"

bool Combo::initialized=false;
vector<int> Combo::lookup;
int Combo::maxracks=0;
int Combo::numracks=0;

Combo::Combo(){
  if(!initialized)throw new Errors::NotInitialized;
  combo=new bool[numracks];
  clear();
}

Combo::Combo(const Combo& other){
  if(!initialized)throw new Errors::NotInitialized;
  combo=new bool[numracks];
  clear();
  for(int n=0;n!=numracks;n++)
    combo[n]=other.combo[n];
}

Combo Combo::operator= (const Combo& other){
  if(!initialized)throw new Errors::NotInitialized;
  clear();
  for(int n=0;n!=numracks;n++)
    combo[n]=other.combo[n];
  return *this;
}

Combo::Combo(vector<int> racks){
  if(!initialized)throw new Errors::NotInitialized;
  combo=new bool[numracks];
  clear();
  addCombo(racks);
}

Combo::~Combo(){delete[] combo;}

bool& Combo::operator[] (int idx){
  if(!initialized)throw new Errors::NotInitialized;
  idx=lookup[idx];
  if(idx>=0 && idx<numracks)return combo[idx];
  else throw new Errors::OutOfBounds;
}

bool Combo::operator[] (int idx) const{
  if(!initialized)throw new Errors::NotInitialized;
  idx=lookup[idx];
  if(idx>=0 && idx<numracks)return combo[idx];
  else throw new Errors::OutOfBounds;
}

void Combo::setLookup(vector<int> l){lookup=l;}
void Combo::setMaxRacks(int m){maxracks=m;}
void Combo::setNumRacks(int n){numracks=n;}

void Combo::init(MYSQL conn){
  ResultSet runparams(&conn);
  int num,max;
  vector<int> look; // lookup[idx] gives a rack's position in the combo string.
  runparams.query<<"select count(idx) as count,max(idx) as max from racks";
  runparams.store();
  if(runparams.next())
    {
      num=(int)runparams["count"];
      max=(int)runparams["max"];
    }
  else throw new Errors::DatabaseError;
  setNumRacks(num);
  setMaxRacks(max);
  look.resize(maxracks+1);
  runparams.query<<"select idx from racks order by idx asc";
  runparams.store();
  if(runparams.size()==0)throw new Errors::DatabaseError;
  int n=0;
  while(runparams.next())
    look[runparams[0]]=n++;
  setLookup(look);
  initialized=true;
}

void Combo::addCombo(vector<int> added){
  if(!initialized)throw new Errors::NotInitialized;
  for(int n=0;n!=added.size();n++)
    (*this)[added[n]]=true;
}

void Combo::clear(){
  if(!initialized)throw new Errors::NotInitialized;
  for(int n=0;n!=numracks;n++)
    combo[n]=false;
}

ostream& operator << (ostream& out,const Combo& combo){
  for(int n=0;n!=Combo::numracks;n++)
    {
      if(combo.combo[n])out<<'1';
      else out<<'0';
    }
  return out;
}
