#include <resultset.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include "ps.h"

// Threshhold for labels
#define T 1.5

using namespace std;

class Line{
public: vector<double> points;string name;
  Line(vector<double> p,string n){points=p;name=n;}
  bool operator< (const Line& b) const {return points<b.points;}
};

vector<double> getPoints(ResultSet res,string table,string resource,int order);
void drawLine(ostream &out,string color,string glyph,vector<double> data);
void drawRow(ostream& out,int row,vector<double> data);
vector<Line> sortLines(vector<Line> lines);
bool isValid(vector<Line>& lines,int line,int point);

int main(int argc, char** argv){

  if(argc!=2 && argc!=8)
    {
      cout<<"Usage: "<<argv[0]<<" <filename> [<host> <user> <pass> <table> <db> <outputdb>]\n";
      return 1;
    }
  string     host=(argc==8?argv[2]:"127.0.0.1");
  string     user=(argc==8?argv[3]:"root");
  string     pass=(argc==8?argv[4]:"blah");
  string      tbl=(argc==8?argv[5]:"fleen");
  string       db=(argc==8?argv[6]:"plum_data");
  string outputdb=(argc==8?argv[7]:"plum_output");

  ofstream out;out.open(argv[1]);
  printFile(out);

  MYSQL conn=ResultSet::makeConn(host,user,pass,db);
  MYSQL dataconn=ResultSet::makeConn(host,user,pass,db);
  ResultSet res(&conn);

  /*
    Glyph names:
    
    circle
    cross
    square
    plus
    diamond
    asterisk
    triangle
    underscore
    smallcircle
    smallsquare
    smalldiamond
    smallasterisk
  */

  res.query<<"select count(idx) from "<<tbl<<" group by selectednum";
  res.store();res.next();int order=res[0];

  vector<Line> lines;

  lines.push_back(Line(getPoints(res,tbl,"any_exceeded_simul",order),"All Resources"));
  drawLine(out,"0.627 0.627 0.976","square",lines[lines.size()-1].points);
  //
  lines.push_back(Line(getPoints(res,tbl,"keepalive_xcd",order),"Keep-alive Power"));
  drawLine(out,"0 0.106 0.357","diamond",lines[lines.size()-1].points);
  //
  lines.push_back(Line(getPoints(res,tbl,"power_xcd",order),"Power"));
  drawLine(out,"0.239 0.843 1","triangle",lines[lines.size()-1].points);
  //
  lines.push_back(Line(getPoints(res,tbl,"acoustics_xcd_simul",order),"Acoustics"));
  drawLine(out,"0.216 0.651 0.604","plus",lines[lines.size()-1].points);
  //
  lines.push_back(Line(getPoints(res,tbl,"MTL_simul_xcd",order),"MTL"));
  drawLine(out,"1 0 1","smallsquare",lines[lines.size()-1].points);
  //
  lines.push_back(Line(getPoints(res,tbl,"LTL_simul_xcd",order),"LTL"));
  drawLine(out,"0.094 0.804 0.094","triangle",lines[lines.size()-1].points);
  //
  lines.push_back(Line(getPoints(res,tbl,"nominal_downlink_xcd",order),"Downlink"));
  drawLine(out,"0.973 0.592 0.361","diamond",lines[lines.size()-1].points);
  //
  lines.push_back(Line(getPoints(res,tbl,"nominal_uplink_xcd",order),"Uplink"));
  drawLine(out,"0 0.424 0","circle",lines[lines.size()-1].points);
  //

  ResultSet sums(&dataconn);
  sums.query<<"select * from sums where simultaneous=1";
  sums.store();
  if(sums.size()!=0)
    while(sums.next())
      {
	lines.push_back(Line(getPoints(res,tbl,string(sums["outputfield"])+"_xcd",order),sums["name"]));
	string color=string(sums["red"])+" "+string(sums["green"])+" "+string(sums["blue"]);
	drawLine(out,color,sums["symbol"],lines[lines.size()-1].points);
      }

  out<<"0 0 0 setrgbcolor\n";

  // labels go here
  vector<Line> slines=sortLines(lines);
  
  double upper=100.0-T;

  for(unsigned n=0;n!=slines.size();n++)
    {
      for(unsigned int j=0;j!=slines[n].points.size();j++)
	{
	  if(slines[n].points[j]<upper && isValid(slines,n,j))
	    {
	      out<<j<<' '<<slines[n].points[j]<<" ("<<slines[n].name<<") drawLabel\n";
	      upper=slines[n].points[j]-T;
	      break;
	    }
	}
    }

  printFooter(out);

  // Table stuff
  vector<string> sumnames;
  if(sums.size()!=0)
    {
      sums.rewind();
      while(sums.next())
	sumnames.push_back(sums["name"]);
    }

  printTable(out,lines[0].points.size(),sumnames);
  for(unsigned int n=0;n!=lines.size();n++)
    drawRow(out,n,lines[n].points);

  printTableFooter(out);
  //

  out.close();
}

bool isValid(vector<Line>& lines,int line,int point){
  double val=lines[line].points[point];
  for(unsigned int n=0;n<lines.size();n++)
    if(n!=(unsigned int) line && abs(lines[n].points[point]-val)<=T)return false;
  return true;
}

vector<Line> sortLines(vector<Line> lines){
  vector<Line> l;
  for(unsigned int n=0;n!=lines.size();n++)
    {
      int len=lines[n].points.size();
      if(lines[n].points[len-1]!=100.0)l.push_back(lines[n]);
    }
  sort(l.begin(),l.end());
  vector<Line> sorted;
  for(int n=l.size()-1;n>=0;n--)
    sorted.push_back(l[n]);
  return sorted;
}

vector<double> getPoints(ResultSet res,string table,string resource,int order){
  res.query<<"select selectednum, sum("<<resource<<") from "<<table<<" group by selectednum order by selectednum asc";
  res.store();

  vector<double> data;

  while(res.next())
    data.push_back(100.0-res[1]/((double)order)*100.0);
  
  return data;
}

void drawRow(ostream& out,int row,vector<double> data){
  out<<"0.5 inch TEXTCELL add 7 inch "<<(row+1)<<" FONTSIZE mul sub NUMBERCELL\n[ ";
  for(unsigned int n=0;n!=data.size();n++)
    out<<'('<<data[n]<<") ";
  out<<"]\ntableRow\n\n";
}

void drawLine(ostream &out,string color,string glyph,vector<double> data){
  out<<color<<" setrgbcolor ("<<glyph<<") 0 [ ";
  for(unsigned int n=0;n<data.size();n++)
    out<<data[n]<<' ';
  out<<" ] drawLine\n\n";
}
