// The library libscl is available at www.aronaldg.org. 
// Click on "Browse webfiles" then on "libscl".

#include "libscl.h"

using namespace std;
using namespace scl;

namespace {

  realmat range(const realmat& X)
  {
    INTEGER n = X.size();
    REAL Xmin = X[1];
    REAL Xmax = X[1];
    for (INTEGER i=1; i<=n; ++i) {
      if (X[i] < Xmin) Xmin = X[i];
      if (X[i] > Xmax) Xmax = X[i];
    }
    realmat rv(2,1);
    rv[1] = Xmin;
    rv[2] = Xmax;
    return rv;
  }

  struct prices {
    REAL pcl;          // Low quality conventional price
    REAL pgl;          // Low quality conventional price
    REAL pch;          // High qualtiy confentional price
    REAL pgh;          // High quality green price
    REAL rev;          // Total revenue
    void initialize() 
    { 
      rev = pcl = pgl = pch = pgh = 0.0; 
    }
    void set(REAL r, REAL cl, REAL gl, REAL ch, REAL gh)
    {
      rev = r; pcl = cl; pgl = gl; pch = ch; pgh = gh;
    }
  };

  ostream& operator<<(ostream& os, prices p)
  {
    cout << "Low quality conventional price  " << fmt('d',5,p.pcl) << '\n';
    cout << "Low quality green price         " << fmt('d',5,p.pgl) << '\n';
    cout << "High quality conventional price " << fmt('d',5,p.pch) << '\n';
    cout << "High quality green price        " << fmt('d',5,p.pgh) << '\n';
    cout << "Total revenue                   " << fmt('d',5,p.rev) << '\n';
    return os;
  }

}

int main(int argc, char** argp, char** envp)
{
  ifstream fin;
  ofstream fout;

  string filename = "lipstick.csv";
  fin.open(filename.c_str());
  if (!fin) error("Error, " + filename + " open failed");
  
  vector<string> string_names;
  vector< vector<string> > strings;
  vector<string> numeric_names; 
  realmat X;
  vector<string> unknown_names;

  INTEGER n
     = csvread(fin,true,string_names,strings,numeric_names,X,unknown_names);

  cout << starbox(string("/Input file " + filename +"//")) << '\n';
  cout << "Number lines read  = " << n+1 << '\n';
  cout << "Number of rows in data = " << X.nrow() << '\n';
  cout << "Number of cols in data = " << X.ncol() << '\n';

  // Col  1  Q2   Age, 1 = 20-25, 2 = 26-30, 3 = 31-
  // Col  2  Q3   Relationship status, 1 = single, 2 = married
  // Col  3  Q4_1 Ingredients
  // Col  4  Q4_2 Color
  // Col  5  Q4_3 Texture
  // Col  6  Q4_4 Lasting quality
  // Col  7  Q4_5 Lipstick packaging
  // Col  8  Q7   WTP ($) C lipstick (Covergirl)  = cl
  // Col  9  Q8   WTP ($) CG lipstick (Body Shop) = gl
  // Col 10  Q6   WTP ($) HQ LB lipstick (Chanel) = ch
  // Col 11  Q5   WTP ($) GHQ as LB               = gh

  realmat WTPcl = X("",8);
  realmat WTPgl = X("",9);
  realmat WTPch = X("",10);
  realmat WTPgh = X("",11);

  realmat rangecl = range(WTPcl);
  realmat rangegl = range(WTPgl);
  realmat rangech = range(WTPch);
  realmat rangegh = range(WTPgh);

  prices best;

  best.initialize();
  for (REAL pcl = rangecl[1]; pcl <= rangecl[2]; ++pcl) {
    for (REAL pgl = rangegl[1]; pgl <= rangegl[2]; ++pgl) {
      for (REAL pch = rangech[1]; pch <= rangech[2]; ++pch) {
        for (REAL pgh = rangegh[1]; pgh <= rangegh[2]; ++pgh) {
          REAL sum = 0.0;
          for (INTEGER k = 1; k <= n; ++k) {
            REAL scl = WTPcl[k] - pcl;
            REAL sgl = WTPgl[k] - pgl;
            REAL sch = WTPch[k] - pch;
            REAL sgh = WTPgh[k] - pgh;
            realmat surplus;
            surplus.push_back(scl);
            surplus.push_back(sgl);
            surplus.push_back(sch);
            surplus.push_back(sgh);
            REAL max_surplus = range(surplus)[2];
            if (max_surplus >= 0.0) {
              if (sgh == max_surplus) {
                sum += pgh;
              }
              else if (sch == max_surplus) {
                sum += pch;
              }
              else if (sgl == max_surplus) {
                sum += pgl;
              }
              else if (scl == max_surplus) {
                sum += pcl;
              }
              else {
                error("Error, this should not happen");
              }
              if (sum > best.rev) {
                best.set(sum,pcl,pgl,pch,pgh);
              }
            }
          }
        }
      }
    }
  }
  cout << '\n';
  cout << starbox("/Optimum lipstick prices//") << '\n';
  cout << best;
  cout << '\n';

  return 0;
}
