#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <cstdlib>
#include <cstdio>
#include <io.h>
#include <direct.h>
#include <strsafe.h>
#include <windows.h>
#include "file.h"
#include "str.h"
#include "st.h"
#include "file.h"

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

typedef vector< string > args_type;

class Remove {
   bool r,f,v;
public:
   Remove() {
      v = false;
      r = false;
      f = false;
   }

   string query_user(const string & src) {
      string ans;
      do {
         cout << "do you want to remove " << src << " [yes/no]: ";
         cin >> ans;
      }
      while(to_lower(ans) != "y" 
            && to_lower(ans) != "ye" 
            && to_lower(ans) != "n" 
            && to_lower(ans) != "yes" 
            && to_lower(ans) != "no");
      if(to_lower(ans) == "y" 
         || to_lower(ans) == "ye"
         || to_lower(ans) == "yes") {
         ans = "yes";
      }
      return ans;
   }

   bool remove(const string & src) {
      list< string > dir_list;
      list< string > dir_list2;
      map< string, bool > the_map;
      string temp;
      char buffer[MAX_PATH];
      bool ret = true;

      memset(buffer, 0, MAX_PATH);

      if(!starts_with(src, "\\")) {
         _getcwd(buffer,MAX_PATH-1);

         size_t sz = strlen(buffer);

         if(sz) {
            if(buffer[sz-1] != '\\') {
               if(sz < MAX_PATH-1) {
                  buffer[sz] = '\\';
               }
            }
         }
      }

      temp = string(buffer) + src;

      dir_list.push_back(temp);

      while(dir_list.size()) {
         temp = dir_list.front();
         dir_list.pop_front();

         File ff(temp);

         if(!ff.exists()) {
            continue;
         }
         
         if(ff.is_directory() && r) {
            if(!ends_with(temp, ".") && !ends_with(temp, "..")) {
               File::dir_vector_type dir;
               if(the_map.find(temp) == the_map.end()) {
                  the_map[temp] = true;
                  dir_list.push_back(temp);
                  dir_list2.push_back(temp);
               }
               ff.dir(dir);
               for(size_t i = 0; i < dir.size(); i++) {
                  if(dir[i].name().size()) {
                     if(dir[i].name()[dir[i].name().size()-1] != '.') {
                        temp = ff.name() + "\\" + dir[i].name();
                        if(the_map.find(temp) == the_map.end()) {
                           the_map[temp] = true;
                           dir_list.push_back(temp);
                           dir_list2.push_back(temp);
                        }
                     }
                  }
               }
            }
         }
         else if(ff.is_file() && ff.exists()) {
            bool flag = true;
            if(!f) {
               if(query_user(ff.name()) != "yes") {
                  flag = false;
               }
            }
            if(flag && ret) {
               if(v) {
                  cout << "remove file: " << ff.name() << endl;
               }
               if(!ff.remove()) {
                  ret = false;
                  break;
               }
            }
         }
      }
      while(dir_list2.size() && ret) {
         temp = dir_list2.back();
         dir_list2.pop_back();
         if(!File(temp).exists()) {
            continue;
         }
         if(!ends_with(temp, ".") && !ends_with(temp, "..") && r) {
            bool flag = true;
            if(!f) {
               if(query_user(temp) != "yes") {
                  flag = false;
               }
            }
            if(flag && r) {
               if(v) {
                  cout << "remove directory: " << temp << endl;
               }
               if(!File(temp).rmdir()) {
                  ret = false;
                  break;
               }
            }
         }
      }
      return ret;
   }

   int run(int argc, char ** argv) { 
      int rc = 0;
      args_type args2;
      int i;
      for(i = 1; i < argc; i++) {
         if(string(argv[i]) == "-f") {
            f = true;
         }
         else if(string(argv[i]) == "-r") {
            r = true;
         }
         else if(string(argv[i]) == "-v") {
            v = true;
         }
         else if(string(argv[i]) == "-rf") {
            r = true;
            f = true;
         }
         else {
            args2.push_back(argv[i]);
         }
      }
      for(i = 0; i < args2.size(); i++) {
         if(!remove(args2[i])) {
            cout << "not found..." << endl;
            break;
         }
      }
      return rc;
   }
};

#ifdef NO_MAIN
extern "C" {
extern int rm_main(int argc, char ** argv);
}
int rm_main(int argc, char ** argv)
#else
int main(int argc, char ** argv)
#endif
{
   Remove rm;
   int rc = 0;
   try {
      rc = rm.run(argc,argv);
   }
   catch(...) {
      cerr << "rm error..." << endl;
      rc = 1;
   }
   return rc;
}
