//in act_wiz.cpp

#include <iostream>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <string>
#include <filesystem>
#include <algorithm>
#include <cctype>

// Helper function to convert a string to lowercase
std::string to_lowercase(const std::string &str) {
    std::string lower_str = str;
    std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), ::tolower);
    return lower_str;
}

/*
 * Searches all area files for a given string and outputs the Vnums and lines where it is found.
 * 
 * progfind <string>
 * case-insensitive
 */

CMDF( do_progfind )
{
     // Adjust the path as necessary to the area folder relative to src
   const std::string AREA_DIR = "../area/";
   const int PATH_BUFFER_SIZE = 1024;

    if (ch->isnpc()) {
        return;
    }

    if (ch->get_trust() < LEVEL_GOD) {
        ch->printf("Sorry, you do not have permission to use this command.\n\r");
        return;
    }

    if (argument.empty()) {
        ch->printf("Syntax: progfind <string>\n\r");
        return;
    }

    std::string search_string = argument;

    // Open the area directory and read each file
    std::string command = "ls " + AREA_DIR + "*.are";
    FILE* pipe = popen(command.c_str(), "r");
    if (!pipe) {
        ch->printf("Error opening area directory.\n\r");
        return;
    }

    char filename[MSL];
    while (fgets(filename, sizeof(filename) - 1, pipe) != nullptr) {
        // Remove newline character from filename
        filename[strcspn(filename, "\n")] = '\0';

        // Ensure filename length is within limits
        if (AREA_DIR.length() + strlen(filename) >= PATH_BUFFER_SIZE) {
            ch->printf("Filename too long, skipping.\n\r");
            continue;
        }

        // Convert the search string to lowercase once for case-insensitive comparison
        std::string search_lower = to_lowercase(search_string);

        // Open the area file
        std::string path_buf = AREA_DIR + filename;
        std::ifstream file(path_buf);
        if (!file.is_open()) {
            ch->printf("Error opening area file.\n\r");
            continue;
        }

        std::string line;
        std::string current_vnum;
        std::string current_section;
        bool in_prog = false;
        bool in_prog_text = false;

        while (std::getline(file, line)) {
         // Detect whether we are in a MOBILE, ROOM, or OBJECT section
         if (line.find("#MOBILE") == 0) {
               current_section = "MOBILE";
         } else if (line.find("#OBJECT") == 0) {
               current_section = "OBJECT";
         } else if (line.find("#ROOM") == 0) {
               current_section = "ROOM";
         }

         // Check for Vnum (i.e., the line starting with "Vnum" followed by the number)
         if (line.find("Vnum") == 0) {
               current_vnum = line.substr(5);  // Get the Vnum after "Vnum"
         }

         // Check for the start of a program
         if (line.find("#MUDPROG") == 0) {
               in_prog = true;
               in_prog_text = false;  // Reset text flag
         }

         // If within a program, check for the search string
         if (in_prog) {
               // Convert current line to lowercase for case-insensitive comparison
               std::string line_lower = to_lowercase(line);
               // Check for program arguments and contents between #MUDPROG and #ENDPROG
               if (line.find('~') != std::string::npos && !in_prog_text) {
                  in_prog_text = true;  // First ~ encountered, start capturing program text
               } 
               else if (in_prog_text) {
                  // Check if the search string is in the program text
                  if (line_lower.find(search_string) != std::string::npos) {
                     // Found the search string within a program, output the information
                     ch->printf("&cFound in VNUM&w: %s, &c(Type&w: %s), &cFile&w: %s\n\r\t&cLine&w: %s&d\n\r", 
                                 current_vnum.c_str(), current_section.c_str(), filename, line.c_str());
                  }

                  // Check for the end of the program (denoted by #ENDPROG)
                  if (line.find("#ENDPROG") == 0) {
                     in_prog = false;  // End of the program
                     in_prog_text = false;
                  }
               }
         }
      }

        file.close();
    }

    pclose(pipe);
    ch->printf("Search complete.\n\r");
}