#include "io_base.h"

#include <cassert>
#include <cstdlib>
#include <regex>

namespace tbplas::base {

bool isValidKey(const std::string& key)
{
    std::regex e(R"(^(\w+\.)*\w+$)");
    bool status = std::regex_match(key, e);
    return status;
}

bool isValidNumbers(const std::string& numbers)
{
    std::regex e(R"(^(-?\d+(\.\d*)?[,])*(-?\d+(\.\d*)?)$)");
    bool status = std::regex_match(numbers, e);
    return status;
}

std::string trimString(const std::string& stringToTrim, char charToTrim)
{
    std::string key_trim_head;
    size_t pos = stringToTrim.find_first_not_of(charToTrim);
    if (pos != std::string::npos) {
        key_trim_head = stringToTrim.substr(pos);
    }
    std::string key_trim_tail;
    pos = key_trim_head.find_last_not_of(charToTrim);
    if (pos != std::string::npos) {
        key_trim_tail = key_trim_head.substr(0, pos + 1);
    }
    return key_trim_tail;
}

std::vector<std::string> splitString(
    const std::string& stringToSplit,
    char separator)
{
    std::string targetstr = trimString(stringToSplit, separator);
    std::vector<std::string> v_path;
    while (!targetstr.empty()) {
        if (targetstr.find(separator) == std::string::npos) {
            v_path.push_back(targetstr);
            break;
        }
        std::string str = targetstr.substr(0, targetstr.find(separator));
        v_path.push_back(str);
        targetstr.erase(0, targetstr.find(separator) + 1);
    }
    return v_path;
}

std::vector<std::string> splitKey(const std::string& key)
{
    return splitString(key, '.');
}

std::vector<double> splitDoubles(const std::string& numbers)
{
    std::vector<std::string> vec_str = splitString(numbers, ',');
    std::vector<double> vec_num;
    vec_num.reserve(vec_str.size());
    for (const auto& s : vec_str) {
        vec_num.push_back(std::stod(s));
    }
    return vec_num;
}

std::vector<int> splitIntegers(const std::string& numbers)
{
    std::vector<std::string> vec_str = splitString(numbers, ',');
    std::vector<int> vec_num;
    vec_num.reserve(vec_str.size());
    for (const auto& s : vec_str) {
        vec_num.push_back(std::stoi(s));
    }
    return vec_num;
}

std::vector<std::string> parseKey(const std::string& key)
{
    std::vector<std::string> keys_split = splitKey(key);
    std::vector<std::string> names;
    if (keys_split.size() == 1) {
        names = { "/", keys_split.back() };
    } else if (keys_split.size() > 1) {
        std::string group_name;
        std::string dataset_name = keys_split.back();
        for (int i = 0; i < keys_split.size() - 1; ++i) {
            group_name += keys_split[i] + ".";
        }
        group_name.pop_back();
        names = { group_name, dataset_name };
    }
    return names;
}

bool BaseFile::isOpen() const
{
    bool status = m_IsOpen;
    return status;
}

bool BaseFile::isClosed() const
{
    bool status = !m_IsOpen;
    return status;
}

void BaseFile::open(const std::string& filePath, bool isOpen)
{
    m_CurFilePath = filePath;
    m_IsOpen = isOpen;
}

void BaseFile::close()
{
    m_CurFilePath = "";
    m_IsOpen = false;
}

} // namespace tbplas::base
