#include <iostream.h>
#include <fstream.h>
#include <string.h>
#include <math.h>
#include <unistd.h>

class Dyntext
{
public:
  Dyntext(const char *filename);
  int nLetters(void);
  int nWords(void);
  int nSentences(void);
  int nTreshold(const int treshold);
  int lix(void);
private:
  char *theText;
  bool in_str(char, const char *);
};

// lookup

char
*wordSeparators = " ()\"-,;\t\n\xd"; // \xd är <lf> \n är <cr>
char
*sentenceEnds = ".?!:";

// prototyper

void showUsage(const char *argvzero);

// class funktioner

bool
Dyntext::in_str(char obj, const char *lookup)
{
  int i=0;
  do
    {
      if (obj == lookup[i])
         return(true);
      i++;
    } while (lookup[i] != 0);
  return(false);
}

Dyntext::Dyntext(const char *filename)
{
  fstream *textFile;
  char tempString[13928];
  int filepos = 0;
 
  if (strcmp("-", filename) == 0) // read stdin
    {
      cout << "Skriv text. Avsluta med ett '#'\n";
      while ((tempString[filepos] = cin.get()) != '#')
         {
           filepos++;
         }
    }
  else
    {
      textFile = new fstream(filename, ios::in);
     
      if (textFile == 0)
         {
           cerr << "Dyntext: filen hittades inte: (" << filename << ")\n";
           exit(true);
         }
      while ((tempString[filepos] = textFile->get()) != EOF)
         {
           filepos++;
         }
    }
  tempString[filepos++] = 0;
  theText = new char[filepos];
  strcpy(theText, tempString);
  return;
}

int
Dyntext::nLetters(void)
{
  int counter=0;
  for (int i=0;i<strlen(theText);i++)
    {
      if(!in_str(theText[i], wordSeparators) && !in_str(theText[i], sentenceEnds)) 
         {
           // apostrof är specialfall
           if (theText[i] != '\'')
             counter++;
         }
    }
  return counter;
}

int
Dyntext::nWords(void)
{
  int counter = 0;
  int i;
  for(i=0; i<strlen(theText) - 1;i++)
    {
      if(in_str(theText[i], wordSeparators)
          && !in_str(theText[i+1], wordSeparators))
         counter++;
    }
  // om den fanns en bokstav i första positionen kommer vi att räkna fel.
  // kompensera!
  if (!in_str(theText[0], wordSeparators))
    counter++;
  return counter;
}

int
Dyntext::nSentences(void)
{
  int counter = 0, i;
  for (i=0;i<=strlen(theText);i++)
    {
      if (in_str(theText[i], sentenceEnds))
         counter++;
    }
  return counter;
}

int
Dyntext::nTreshold(const int treshold)
{
  int wordlen=0, counter=0, i;
  for (i=0;i<strlen(theText);i++)
    {
      if(in_str(theText[i], wordSeparators) || in_str(theText[i], sentenceEnds))
         wordlen=0;
      else
         if (theText[i] != '\'')
           wordlen++;
      if ((wordlen == treshold) && (theText[i] != '\''))
         counter++;
    }
  return counter;
}

int
Dyntext::lix(void)
{
  int sentnum, meansentlen, diffwordsratio;
  // undvik ondska om det inte finns meningsslut.
  if ((sentnum = nSentences()) == 0)
    meansentlen=0;
  else
    meansentlen = (int) floor(nWords() / sentnum);
  diffwordsratio = (int) floor(100*nTreshold(7)/nWords());

  return meansentlen + diffwordsratio;
}

int
Interactive(char *[]);

int
main(int argc, char *argv[])
{
  Dyntext *text;
  int i=1;

  if (argc < 2)
    argc = Interactive(argv) + 1;
  if (argc == 2 && strncmp("-h",argv[1], 2) == 0)
    {
      showUsage(argv[0]);
      return(false);
    }
  text = new Dyntext(argv[1]);
  cout << "filnamn\t\tbokstäver\tord\tmeningar\tsju+-ord\tlix\n\n";
  while(1)
    {
     
      cout.form("%7s ", argv[i]) << "\t";
      cout << text->nLetters() << "\t\t";
      cout << text->nWords() << "\t";
      cout << text->nSentences() << "\t\t";
      cout << text->nTreshold(7) << "\t\t";
      cout << text->lix() << "\n";
      if (++i < argc)
         text = new Dyntext(argv[i]);
      else
         break;
    }
  cout << "\nVäntar 30 sekunder...";
  cout.flush();
  sleep(30);
  return(false);
}

void showUsage(const char *argvzero)
{
  cout << "Användning: " << argvzero << " <filnamn1> [filnamn2] ... \n\n";
}

int
Interactive(char *argv[])
{
  char *buf = new char[256];
  char *nexttok;
  int i=1;
 
  cout << "(En ensam '-' betyder att programmet läser från stdin)\n";
  cout << "Skriv namnet på filerna som skall undersökas med kolon emellan\n$ ";
  cin >> buf;

  // Om man har en variabel som heter *argv[] får man använda svart magi
  // (Gammalt unix-ordspråk) ;-)
  if ((nexttok = strtok(buf, ":")) == NULL)
    exit(true);
  argv[1] = new char[strlen(nexttok)];
  strcpy(argv[1], nexttok);
  while ((nexttok = strtok(NULL, ":")) != NULL)
    {
      argv[++i] = new char[strlen(nexttok)];
      strcpy(argv[i], nexttok);
    }
  // vi hittade 'i' tokens
  return i;
}