
#define __USE_POSIX199309

#include <sys/time.h>
#include <sys/vfs.h>
#include <time.h>

#include <unistd.h>

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <string>

#include <renderer.h>
#include <imlibrenderer.h>
#include <dmyrenderer.h>
#include <scan.h>

using std::string;

#define fail -1
#define success 0
#define TB 1

      enum ConditionArgumentType
      {
         catUnknown,
         catInteger,
         catString
      };

//***************************************************************************
// 
//***************************************************************************

int parseVariable(string& toParse)
{
   string name, value;
   Scan scan(toParse.c_str());

   scan.eat();
   
   if (!scan.isIdent())
   {
      printf("Error: Invalid left value '%s' in '%s'\n",
           scan.lastIdent(), toParse.c_str());
      return fail;
   }

   name = scan.lastIdent();

   scan.eat();

   if (!scan.isOperator() || scan.lastIdent()[0] != '=')
   {
      printf("Error: Invalid operator '%s' in '%s', '=' expected\n", 
           scan.lastIdent(), toParse.c_str());
      return fail;
   }

   scan.eat();

   if (!scan.isString() && scan.isIdent())
   {
      printf("Error: Invalid right value '%s' in '%s'\n",
           scan.lastIdent(), toParse.c_str());
      return fail;
   }

   value = scan.lastIdent();

   printf("'%s' = '%s'\n", name.c_str(), value.c_str());
  
   return success;
}

//***************************************************************************
// evaluate the condition (prepare for string operation later ..)
//***************************************************************************

int condition(int left, int right, const char* op)
{
   printf("evaluate integer condition '%d' '%s' '%d'\n", 
          left, op, right);

   if (strcmp(op, ">") == 0)
      return left > right;
   
   if (strcmp(op, "<") == 0)
      return left < right;
   
   if (strcmp(op, ">=") == 0)
      return left >= right;
   
   if (strcmp(op, "<=") == 0)
      return left <= right;
   
   if (strcmp(op, "=") == 0 || strcmp(op, "==") == 0)
      return left == right;
   
   if (strcmp(op, "!=") == 0 || strcmp(op, "<>") == 0)
      return left != right;

   printf("Unexpected operator '%s'", op);

   return no;
}

int condition(string* left, string* right, const char* op)
{
   printf("evaluate string condition '%s' '%s' '%s'\n", 
          left->c_str(), op, right->c_str());

   if (strcmp(op, ">") == 0)
      return *left > *right;
   
   if (strcmp(op, "<") == 0)
      return *left < *right;
   
   if (strcmp(op, ">=") == 0)
      return *left >= *right;
   
   if (strcmp(op, "<=") == 0)
      return *left <= *right;
   
   if (strcmp(op, "=") == 0 || strcmp(op, "==") == 0)
   {
      printf("do compare -> %d\n", *left == *right);
      return *left == *right;
   }
   
   if (strcmp(op, "!=") == 0 || strcmp(op, "<>") == 0)
      return *left != *right;

   printf("Unexpected operator '%s'", op);

   return no;
}

int evaluateCondition(int recurse, string _condition)
{
   static Scan* scan = 0;

   int result;
   int state;

   int rightType = catUnknown;
   int leftType = catUnknown;
   int leftInt = 0;
   int rightInt = 0;
   string leftStr = "";
   string rightStr = "";

   char op[100]; *op = 0;
   char logicalOp[100]; *logicalOp = 0;
   string expression;

   if (!recurse || !scan)
   {
      if (_condition.size() <= 0)
         return yes;

      printf("evaluate '%s'\n", _condition.c_str());

      scan = new Scan(_condition.c_str());
   }

   // left expression

   scan->eat();

   if (scan->isNum())
   {
      leftInt = scan->lastInt();
      leftType = catInteger;
   }
   else if (scan->isString())
   {
      leftStr = scan->lastString();
      leftType = catString;
   }
   else
   {
      printf("Error: Invalid left '%s' expression in '%s'\n",
           scan->lastIdent(), expression.c_str());
      return no;
   }

   // operator ?

   if ((state = scan->eat()) == success && scan->isOperator() && !scan->isLogical())
   {
      strcpy(op, scan->lastIdent());
      
      // right expression
      
      scan->eat();
      
      if (scan->isNum())
      {
         rightInt = scan->lastInt();
         rightType = catInteger;
      }
      else if (scan->isString())
      {
         rightStr = scan->lastString();
         rightType = catString;
      }
      else
      {
         printf("Error: Invalid right '%s' expression in '%s'\n",
              scan->lastIdent(), expression.c_str());
         return no;
      }    
      
      // check the condition

      if (leftType != rightType)
      {
         printf("Error: Argument types of left and right "
              "agrument don't match in (%d/%d) '%s'\n",
              leftType, rightType, expression.c_str());
         return no;
      }    

      if (leftType == catInteger)         
         result = condition(leftInt, rightInt, op);
      else
         result = condition(&leftStr, &rightStr, op);

      state = scan->eat();
   }
   else if (leftType == catInteger)
   {
      result = leftInt ? true : false;
   }
   else
   {
      result = leftStr != "" ? true : false;
   }

   // any more expressions in here?

   printf("check for further condition at '%s'\n", Str::notNull(scan->next()));

   if (state == success)
   {
      printf("further condition found\n");

      if (!scan->isLogical())
      {
         printf("Error: Invalid logical operator '%s' expression in '%s'\n",
              scan->lastIdent(), expression.c_str());
         return no;
      }

      strcpy(logicalOp, scan->lastIdent());

      // start a recursion ...

      if (strncmp(logicalOp, "&", 1) == 0)
         result = result && evaluateCondition(yes, _condition);
      else if (strncmp(logicalOp, "|", 1) == 0)
         result = result || evaluateCondition(yes, _condition);
   }

   delete scan; scan = 0;

   printf("condition is '%s'; result is '%s'\n", 
        _condition.c_str(), result ? "match" : "don't match");

   return result;
}

void testImlib(const char* text)
{
   DummyRenderer r(0,0,800,600,"/etc/vdr/plugins", yes, "/etc/vdr/plugins/graphTFT/themes/avp");

   r.setBorder(0,0);
   r.init(1);
   r.setPlayMode(no);

   r.text(text,
          "/etc/vdr/plugins/graphTFT/themes/avp/fonts/graphTFT.ttf", 22, 0,
          10, 10,
          255, 255, 255,
          100, 40, 1,
          no);

}

//***************************************************************************
// tescht
//***************************************************************************

int main(int argc, char** argv)
{
//    text("hallo xxx xxx", 40, 14, 9);
//    text("\uE001\uE001\uE001\uE001\uE002", 50, 14, 9);
//    text("\uE001\uE001\uE001\uE001\uE001", 50, 14, 9);
//    text("?\200\201?\200\202", 50, 14, 9);

//    if (argc > 1)
//       text(argv[1], 100, 14, 2);


   if (argc < 2)
      return 1;

   testImlib(argv[1]);

   return 0;


   string tmp = argv[1];

   // parseVariable(tmp);

   if (evaluateCondition(no, tmp))
      printf("-> true\n");
   else
      printf("-> false\n");

   return 0;
}
