
#include "pch.h"
#include <iostream>
#include <fstream>
#include <iostream>
#include <string>
#include "Shot.h"
#include <filesystem>
#include <regex>
#include <charconv>
namespace fs = std::filesystem;
using namespace std;





Shot::Shot() {



}

bool Shot::readShotFile(std::string filePath1, std::string shotName1) {
    int lastSlashPos = filePath1.find_last_of('/');
    std::string tempFilePath = "eeeeeeeeeeeeeeee";
    if (lastSlashPos != filePath1.length() - 1) {
        return false;
    }
    if (!(shotName1 == "")) {
        std::regex shotPattern("^Shots\\d+$");
        if (std::regex_match(shotName1, shotPattern)) {
            tempFilePath = filePath1 + shotName1 + ".txt";
        }
        else {
            tempFilePath = filePath1 + shotName1 + ".shot";
        }
        

    }
    else {
        return false;
    }

    if (fs::exists(tempFilePath) && fs::is_regular_file(tempFilePath)) {
        filePath = tempFilePath;
        folderPath = filePath1;
        shotName1 = shotName;
        return read();
    }
    else {
        return false;
    }
}
bool Shot::createShotFile(std::string filePath1, float height1, float length1, float width1, float speedX1, float speedY1, float speedZ1, float carX1, float carY1, float carZ1, int carYaw1, std::string shotName1, int ball1Speed1, int carPitch1, int carRoll1) {
    int lastSlashPos = filePath1.find_last_of('/');
    std::string tempFilePath = "eeeeeeeeeeeeeeee";
    if (lastSlashPos != filePath1.length() - 1) {
        return false;
    }
    if (!(shotName1 == "")) {
        tempFilePath = filePath1 + shotName1 + ".shot";
        if (!fs::exists(tempFilePath)) {
            filePath = tempFilePath;
            setShot(height1, length1, width1, speedX1, speedY1, speedZ1, carX1, carY1, carZ1, carYaw1, shotName1, ball1Speed1, carPitch1, carRoll1);
            return true;
        }
    }
    return false;

}
bool Shot::createDefaultShotFile(std::string filePath1) {
    int lastSlashPos = filePath1.find_last_of('/');
    if (lastSlashPos != filePath1.length() - 1) {
        return false;
    }
    std::string tempFilePath = filePath1 + "defaultShot.shot";
    if (!fs::exists(filePath)) {
        filePath = tempFilePath;
        setShot(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, "defaultShot", 3000, 0, 0);
        return true;
    }
    else {
        return false;
    }
}
inline bool Shot::fileExists(const std::string& name) {
    struct stat buffer;
    return (stat(name.c_str(), &buffer) == 0);
}
void Shot::setShot(float height1, float length1, float width1, float speedX1, float speedY1, float speedZ1, float carX1, float carY1, float carZ1, int carYaw1, string nameShot1, int ball1Speed1, int carPitch1, int carRoll1) {

    shotheight = height1;
    shotlength = length1;
    shotwidth = width1;
    shotspeedX = speedX1;
    shotspeedY = speedY1;
    shotspeedZ = speedZ1;
    shotcarX = carX1;
    shotcarY = carY1;
    shotcarZ = carZ1;
    shotcarYaw = carYaw1;
    shotcarPitch = carPitch1;
    shotcarRoll = carRoll1;
    shotName = nameShot1;
    ball1Speed = ball1Speed1;
    write();
}
bool Shot::deleteShotFile() {
    if (fs::exists(filePath)) {
        try {
            fs::remove(filePath);
        }
        catch (std::exception& e) {
            return false;
        }
        
        return true;
    }
    else {
        return false;
    }
}
bool Shot::renameShot(std::string newName) {
    if (!(newName == "")) {
        std::string newFilePath = folderPath + newName + ".shot";
        try {
            fs::rename(filePath, newFilePath);
        }catch(std::exception& e) {
            return false;
        }
        
        filePath = newFilePath;
        shotName = newName;
        write();
        return true;
    }
    return false;
}
float Shot::getHeight() const {
    return shotheight;
}
float Shot::getLength() const {
    return shotlength;
}
float Shot::getWidth() const {
    return shotwidth;
}
float Shot::getSpeedX() const {
    return shotspeedX;
}
float Shot::getSpeedY() const {
    return shotspeedY;
}
float Shot::getSpeedZ() const {
    return shotspeedZ;
}
float Shot::getCarX() const {
    return shotcarX;
}
float Shot::getCarY() const {
    return shotcarY;
}
float Shot::getCarZ() const {
    return shotcarZ;
}
int Shot::getCarYaw() const {
    return shotcarYaw;
}
int Shot::getCarPitch() const {
    return shotcarPitch;
}
int Shot::getCarRoll() const {
    return shotcarRoll;
}
int Shot::getBallSpeed() const {
    return ball1Speed;
}
string Shot::getShotName() const{
    return underscoreToSpace(shotName);
}
bool Shot::isEmpty() {
    
    if (shotheight != 0.0f) return false;
    if (shotlength != 0.0f) return false;
    if (shotwidth != 0.0f) return false;
    if (shotspeedX != 0.0f) return false;
    if (shotspeedY != 0.0f) return false;
    if (shotspeedZ != 0.0f) return false;
    if (shotcarX != 0.0f) return false;
    if (shotcarY != 0.0f) return false;
    if (shotcarZ != 0.0f) return false;
    if (ball1Speed != 3000.0f) return false;
    std::regex shotPattern("^Shot\\d+$");
    if (!std::regex_match(shotName, shotPattern) && shotName != "3000" && shotName != "") return false;
    if (shotcarYaw != 0) return false;
    if (shotcarPitch != 0 && shotcarPitch != 137463) return false;
    if (shotcarRoll != 0 && shotcarRoll != 137463) return false;
    
    return true;
}
//file manipulation
void removeBadChars(string& str) {
    std::string badChars = "/\\|*?\"<>";
    str.erase(
        std::remove_if(str.begin(), str.end(),
            [&badChars](char c) { return badChars.find(c) != std::string::npos; }),
        str.end()
    );
    
}
void Shot::write() {

    string nSpace = trimUnderscores(shotName);
    removeBadChars(nSpace);
    nSpace = spaceToUnderscore(nSpace);
    ofstream fout(filePath, std::ios::trunc);
    if (!fout.is_open()) return;
    fout << shotheight << ' ' << shotlength << ' ' << shotwidth << ' ' << shotspeedX << ' ' << shotspeedY << ' ' << shotspeedZ << ' ' << shotcarX << ' ' << shotcarY << ' ' << shotcarZ << ' ' << shotcarYaw << ' ' << nSpace << ' ' << ball1Speed << ' ' << shotcarPitch << ' ' << shotcarRoll;
    fout.close();
}
bool Shot::read() {
    ifstream fin(filePath);
    if (!fin.is_open()) return false;
    fin >> shotheight >> shotlength >> shotwidth >> shotspeedX >> shotspeedY >> shotspeedZ >> shotcarX >> shotcarY >> shotcarZ >> shotcarYaw >> shotName >> ball1Speed >> shotcarPitch >> shotcarRoll;
    fin.close();
    return updateShots();
}

bool Shot::updateShots() {
    bool notDeleted = true;

    char cutoff = '.';
    string name;
    int pos = filePath.find_last_of(cutoff); 
    int lastSlashPos = filePath.find_last_of('/');
    if (pos != std::string::npos && lastSlashPos != std::string::npos && pos> lastSlashPos) {
        name = filePath.substr(lastSlashPos + 1, pos - (lastSlashPos + 1));
    }
    removeBadChars(shotName);
    removeBadChars(name);
    shotName = trimUnderscores(shotName);
    shotName = underscoreToSpace(shotName);
    if (!(shotName == name)) {
        string newFilePath = folderPath + shotName + ".shot";
        int i = 1;
        while (fs::exists(newFilePath)) {
			shotName += std::to_string(i);
            newFilePath = folderPath + shotName + ".shot";
            i++;
        }
        
        try {
            fs::rename(filePath, newFilePath);
        }
        catch (std::exception& e) {
            return false;
        }

        filePath = newFilePath;
        if (isEmpty()) {
            try {
                fs::remove(newFilePath);
            }
            catch (std::exception& e) {
                return true;
            }
            notDeleted = false;
        }
        else {
            write();
        }
    }
        
    return notDeleted;
}
std::string Shot::trimUnderscores(const std::string& input) {
    size_t start = 0;
    size_t end = input.size();

    // Move start index forward past leading underscores
    while (start < end && input[start] == '_') {
        ++start;
    }

    // Move end index backward past trailing underscores
    while (end > start && input[end - 1] == '_') {
        --end;
    }

    return input.substr(start, end - start);
}
string Shot::spaceToUnderscore(string shotName1) {
    for (std::string::iterator it = shotName1.begin(); it != shotName1.end(); ++it) {
        if (*it == ' ') {
            *it = '_';
        }
    }

    return shotName1;
}
string Shot::underscoreToSpace(string shotName1) const {
    for (std::string::iterator it = shotName1.begin(); it != shotName1.end(); ++it) {
        if (*it == '_') {
            *it = ' ';
        }
    }
    return shotName1;
}

