#include <windows.h>
#include <iostream>
#include <string>
#include <direct.h>
#include "str.h"
#include "str_tok.h"
#include "file.h"

using namespace std;
using namespace string_tools;
using namespace io_tools;

bool file_exists(const string & ff) {
   File file(ff);
   return file.is_file();
}

bool in_path(const string & file_name, string & path) {
   bool ret = false;
   string current_path;
   path = "";
   const char * real_path0 = getenv("PATH");
   if(real_path0) {
      string temp = real_path0;
      char current_dir[MAX_PATH];
      memset(current_dir, 0, MAX_PATH);
      _getcwd(current_dir, MAX_PATH-1);
      temp = string(current_dir) + ";" + temp; 
	   char* real_path = Strdup(temp.c_str());
	   string_tokenizer st(real_path, ";");
      while(st.has_next()) {
          current_path = st.get_next();
          if(!ends_with(current_path, "\\")) {
             current_path += "\\";
          }
          if(file_exists(current_path + file_name)) {
            path = current_path;
            ret = true;
            break;
          }
      }
	   delete [] real_path;
   }
   return ret;
}

class which {
public:
   int run(int argc, char ** argv) {
      int rc = 0;
      string prog,path;
      for(int i = 1; i < argc; i++) {
         try {
            prog = argv[i];
            if (!ends_with(prog, ".exe")) {
               prog += ".exe";
            }
            if (in_path(prog, path)) {
               cout << path << prog << endl;
            }
         }
         catch (bad_alloc ex) {
            cout << "bad allocation..." << endl;
            rc = 1;
         }
         catch (const char* mm) {
            cout << mm << endl;
            rc = 1;
         }
         catch (...) {
            cout << "which exception..." << endl;
            rc = 1;
         }
      }
      return rc;
   }
};

#ifdef NO_MAIN
extern "C" {
extern int which_main(int argc, char ** argv);
}
int which_main(int argc, char ** argv)
#else
int main(int argc, char ** argv)
#endif
{
   which WHICH;
   WHICH.run(argc,argv);
   return 0;
}
