#ifndef __CCCC_MET_H
#define __CCCC_MET_H

#include <strstream.h>

#include "cccc_stg.h"

#ifndef MAX_TREATMENT_RECORDS
#define MAX_TREATMENT_RECORDS 100
#endif

enum EmphasisLevel { elLOW=0, elMEDIUM=1, elHIGH=2 };

class CCCC_Html_Stream;

// the single class CCCC_Metric which will be defined later in this file 
// will be used for all metrics
// differences in output formats will be handled by giving each object
// of type CCCC_Metric a pointer to a an object of type Metric_Treatment
// which will be held in a global array called Metric_Treatment_Table
class Metric_Treatment
{
  friend class CCCC_Metric;
  friend class Metric_Treatment_Table;
  friend CCCC_Html_Stream& operator <<(CCCC_Html_Stream&,const CCCC_Metric&);

  // a short code string is used to search for the metric treatment, and
  // it has a full name
  CCCC_String code, name;
  
  // lower_threshold and upper_threshold are the levels at which the metric
  // is interpreted as moving between low, medium and high emphasis levels
  float lower_threshold, upper_threshold;
  
  // for ratio type metrics, we provide the facility for screening out of 
  // items for which the numerator lies below a given value
  // e.g. we may impose a standard of 1 line of comment per 3 of code, but
  // say that we do not require this standard to apply to routines shorter
  // than 5 lines
  int numerator_threshold;
  
  // preferred display width and number of decimal places
  int width, precision;

public:  
  Metric_Treatment(istream& is);
};

class Metric_Treatment_Table
{
  Metric_Treatment* records[MAX_TREATMENT_RECORDS];
public:
  Metric_Treatment* lookup(const CCCC_String& metric_code);
  Metric_Treatment_Table(istream& is);
};

extern Metric_Treatment_Table *treatment_table;

// the main metric class
class CCCC_Metric {
    Metric_Treatment* treatment;
    float numerator, denominator;
    friend CCCC_Metric& operator+(const CCCC_Metric&, const CCCC_Metric&);

     
 public:
    CCCC_Metric() { set_ratio(0,0); set_treatment(""); }
    CCCC_Metric(int n, const char* treatment_tag="") { 
      set_ratio(n,1); set_treatment(treatment_tag); 
    }
    CCCC_Metric(int n, int d, const char* treatment_tag="") { 
      set_ratio(n,d); set_treatment(treatment_tag); 
    }

    void set_treatment(const CCCC_String& code) {
      treatment=treatment_table->lookup(code);
    }

    void set_ratio(float _num, float _denom=1.0) { 
      numerator=_num; denominator=_denom;
    }
   
    EmphasisLevel emphasis_level() const 
    { 
      EmphasisLevel retval=elLOW;
      if(treatment!=NULL && numerator>treatment->numerator_threshold)
      {
	if( numerator > (treatment->upper_threshold*denominator) )
	{
	  retval=elHIGH;
	} 
	else if(numerator> (treatment->lower_threshold*denominator) )
	{
	  retval=elMEDIUM;
	}
      }
      return retval;
    }

    const CCCC_String& code() const 
    { 
       static CCCC_String retval;
       if(treatment != NULL) { retval=treatment->code; }
       return retval; 
    }
    const CCCC_String& name() const 
    { 
       static CCCC_String retval;
       if(treatment != NULL) { retval=treatment->name; }
       return retval; 
    }
    
    const CCCC_String& value_string() const;
};
    

    
#endif /* __CCCC_MET_H */








