#include "boost/regex.hpp"
#include <boost/algorithm/string/regex.hpp>
#include "case_reader.h"
#include "fstream"
#include "vector"

CaseReader::CaseReader(const string &filePath, int ptDim) {
    srf1.ptDim = ptDim;
    srf2.ptDim = ptDim;
    initVertices1(handleFile(filePath));
}

CaseReader::CaseReader(const string &filePath1, const string &filePath2, int ptDim) {
    srf1.ptDim = ptDim;
    srf2.ptDim = ptDim;
    initVertices2(handleFile(filePath1), srf1);
    initVertices2(handleFile(filePath2), srf2);
}

string CaseReader::handleFile(const string &filePath) {
    ifstream fin;
    fin.open(filePath);
    if (!fin) {
        cout << "File Open Error!" << endl;
    }
    string str;
    string tmp;
    while (fin.good()) {
        getline(fin, tmp);
        str += tmp + "\n";
    }
    fin.close();

//    initVertices1(str);
    return str;
}

void CaseReader::initVertices1(const string &str) {
    vector<string> infos;
    boost::algorithm::split(infos, str, boost::is_any_of(";"));
    auto wData = infos[0], srf1Data = infos[1], srf2Data = infos[2];

    getPtsFromStr1(srf1Data, srf1);
    getPtsFromStr1(srf2Data, srf2);

    wData = regex_replace(wData, boost::regex(R"((^(.)*Matrix( )*\(( )*\[( )*\[)|(\]( )*\]( )*\)( )*(.)*$))"), "");
    vector<string> ws;
    split_regex(ws, wData, boost::regex("( )*\\]( )*,( )*\\[( )*"));

    for (int i = 0; i < ws.size(); i++) {
        vector<string> lineWs;
        split_regex(lineWs, ws[i], boost::regex("( )*,( )*"));
        for (int j = 0; j < lineWs.size(); j++) {
            int baseIdx = (i * static_cast<int>(lineWs.size()) + j) * 4;
            srf1.vertex[baseIdx + 3] = stod(lineWs[j]);
            srf1.vertex[baseIdx] *= srf1.vertex[baseIdx + 3];
            srf1.vertex[baseIdx + 1] *= srf1.vertex[baseIdx + 3];
            srf1.vertex[baseIdx + 2] *= srf1.vertex[baseIdx + 3];

            srf2.vertex[baseIdx + 3] = stod(lineWs[j]);
            srf2.vertex[baseIdx] *= srf2.vertex[baseIdx + 3];
            srf2.vertex[baseIdx + 1] *= srf2.vertex[baseIdx + 3];
            srf2.vertex[baseIdx + 2] *= srf2.vertex[baseIdx + 3];

            printf("(%g, %g, %g, %g) ", srf1.vertex[baseIdx], srf1.vertex[baseIdx + 1], srf1.vertex[baseIdx + 2],
                   srf1.vertex[baseIdx + 3]);
        }
//        printf("\n");
    }

}

void CaseReader::getPtsFromStr1(string &srfData, Srf &srf) {

    srfData = regex_replace(srfData, boost::regex("^(.)*Matrix( )*\\("), "");
    srfData = regex_replace(srfData, boost::regex("\\}( )*\\)$"), "");

    vector<string> dimsAndPts;
    split_regex(dimsAndPts, srfData, boost::regex("( )*\\{( )*"));
    auto dimsData = dimsAndPts[0];
    auto ptsData = dimsAndPts[1];

    vector<string> dims;
    split_regex(dims, dimsData, boost::regex("( )*,( )*"));
    srf.dim_u = stoi(dims[0]);
    srf.dim_v = stoi(dims[1]);

    // 默认bezier
    srf.degree_u = srf.dim_u - 1;
    srf.degree_v = srf.dim_v - 1;

    srf.knots_num_u = 2;
    srf.knots_num_v = 2;

    srf.knots_u = new double[srf.knots_num_u];
    srf.knots_v = new double[srf.knots_num_v];

    srf.knots_u[0] = 0;
    srf.knots_u[1] = 1;
    srf.knots_v[0] = 0;
    srf.knots_v[1] = 1;

    srf.knots_mult_u = new int[srf.knots_num_u];
    srf.knots_mult_v = new int[srf.knots_num_v];
    srf.knots_mult_u[0] = srf.dim_u;
    srf.knots_mult_u[1] = srf.dim_u;
    srf.knots_mult_v[0] = srf.dim_v;
    srf.knots_mult_v[1] = srf.dim_v;

    vector<string> pts;
    split_regex(pts, ptsData, boost::regex("( )*,( )*\\("));

    delete[] srf.vertex;
    srf.vertex = new double[srf.dim_u * srf.dim_v * srf.ptDim];

    if (pts.size() != srf.dim_u * srf.dim_v) {
        printf("control points size error!\n");
    }
    for (int i = 0; i < srf.dim_u; i++) {
        for (int j = 0; j < srf.dim_v; j++) {
            vector<string> pt;
            split_regex(pt, pts[i * srf.dim_v + j], boost::regex("( )*=( )*"));
            auto ptCoords = pt[1];
            boost::algorithm::erase_all(ptCoords, "[");
            boost::algorithm::erase_all(ptCoords, "]");
            vector<string> xyz;
            split_regex(xyz, ptCoords, boost::regex("( )*,( )*"));
            if (xyz.size() != 3) {
                printf("coord element cnt error!\n");
            }
            for (int k = 0; k < 3; k++) {
                double num;
                auto coordChar = xyz[k];
                if (coordChar.find('/') != string::npos) {
                    vector<string> nums;
                    split_regex(nums, coordChar, boost::regex("( )*/( )*"));
                    num = stod(nums[0]) / stod(nums[1]);
                } else {
                    num = stod(coordChar);
                }
                srf.vertex[(i * srf.dim_v + j) * srf.ptDim + k] = num;
            }
//            printf("(%g, %g, %g) ", resVertex[(i * dim_v + j) * 4], resVertex[(i * dim_v + j) * 4 + 1],
//                   resVertex[(i * dim_v + j) * 4 + 2]);
        }
//        printf("\n");
    }
//    cout << "regex_match: " << boost::regex_match(srfData, expr) << endl;
    int a = 1;

//    std::string my_stringB = "2020 Happy New Year !!!";
//
//    boost::regex regxA("^(\\d| )*");    // 匹配开头数字
//    boost::regex regxB("!*$");         // 匹配末尾标点符号
//
//    cout << regex_replace(my_stringB, regxA, "2021") << endl;
//    cout << regex_replace(my_stringB, regxB, "") << endl;
}

CaseReader::~CaseReader() {
}

double *CaseReader::getPtsFromStr2(string &srfData) {

    return nullptr;
}

void CaseReader::initVertices2(const string &str, Srf &srf) {

    boost::regex p(R"(-8\.\d+,)");
    vector<string> res;

    vector<string> infos;
    // 将str中的信息以正则表达式nextLine为分隔符进行分割,存入infos中,这个真正表达式是\n或者\r或者\r\n三种换行符中的任意一种
    // 这里真正表达式中三个子式的顺序非常重要,因为在匹配时,会按照子式的顺序进行匹配,如何\r在前,那么\r\n就不会匹配到,因为\r\n已经被\r匹配到了,但是\n还是会被匹配,这样就会被匹配两次,\r和\n之间会被分割出一个空串
    boost::regex nextLine(R"(((\r\n)|(\r)|(\n))+)");
//    boost::regex nextLine(R"(((\r)|(\r\n)|(\n)){1})");
    boost::sregex_token_iterator it(str.begin(), str.end(), nextLine, -1); // -1表示不包含分隔符
    boost::sregex_token_iterator end;
    for (; it != end; ++it) {
        infos.emplace_back(it->str());
    }

    auto degrees = extractSubStr(infos[0], "\\d+");
    srf.degree_u = stoi(degrees[0]);
    srf.degree_v = stoi(degrees[1]);

    auto dims = extractSubStr(infos[1], "\\d+");
    srf.dim_u = stoi(dims[0]);
    srf.dim_v = stoi(dims[1]);

    // 最外面加了个括号是因为|的优先级很低,括号防止|并到更长的子式
    string regexExprForNum = R"(-?((\d+\.?\d*)|(\d*\.?\d+)))";

    auto knotsVec_u = extractSubStr(infos[2], regexExprForNum);
    vector<int> knotsVec_mult_u;
    srf.knots_num_u = 0;

    for (int i = 0; i < knotsVec_u.size(); i++) {
        if (i == 0 || stod(knotsVec_u[i]) != stod(knotsVec_u[i - 1])) {
            // 用独特的值覆盖重复的值
            knotsVec_u[srf.knots_num_u] = knotsVec_u[i];
            srf.knots_num_u++;
            knotsVec_mult_u.emplace_back(1);
        } else {
            knotsVec_mult_u[srf.knots_num_u - 1]++;
        }
    }

    delete[] srf.knots_u;
    srf.knots_u = new double[srf.knots_num_u];
    delete[] srf.knots_mult_u;
    srf.knots_mult_u = new int[srf.knots_num_u];
    for (int i = 0; i < srf.knots_num_u; i++) {
        srf.knots_u[i] = stod(knotsVec_u[i]);
        srf.knots_mult_u[i] = knotsVec_mult_u[i];
    }

    auto knotsVec_v = extractSubStr(infos[3], regexExprForNum);
    vector<int> knotsVec_mult_v;
    srf.knots_num_v = 0;
    for (int i = 0; i < knotsVec_v.size(); i++) {
        if (i == 0 || stod(knotsVec_v[i]) != stod(knotsVec_v[i - 1])) {
            // 用独特的值覆盖重复的值
            knotsVec_v[srf.knots_num_v] = knotsVec_v[i];
            srf.knots_num_v++;
            knotsVec_mult_v.emplace_back(1);
        } else {
            knotsVec_mult_v[srf.knots_num_v - 1]++;
        }
    }

    delete[] srf.knots_v;
    srf.knots_v = new double[srf.knots_num_v];
    delete[] srf.knots_mult_v;
    srf.knots_mult_v = new int[srf.knots_num_v];
    for (int i = 0; i < srf.knots_num_v; i++) {
        srf.knots_v[i] = stod(knotsVec_v[i]);
        srf.knots_mult_v[i] = knotsVec_mult_v[i];
    }

    if (knotsVec_u.size() != srf.dim_u + srf.degree_u + 1) {
        printf("knots_u size error!\n");
        return;
    }
    if (knotsVec_v.size() != srf.dim_v + srf.degree_v + 1) {
        printf("knots_v size error!\n");
        return;
    }

    delete[] srf.vertex;
    srf.vertex = new double[srf.dim_u * srf.dim_v * srf.ptDim];

    for (int i = 0; i < srf.dim_u; i++) {
        auto regexExprForPt = regexExprForNum;
        // 注意这里不能写成链式的,因为有append自己的操作,而每次append又会改变自己,就会造成重复append
        regexExprForPt.append(", *");
        regexExprForPt.append(regexExprForNum);
        regexExprForPt.append(", *");
        regexExprForPt.append(regexExprForNum);
        auto pts = extractSubStr(infos[i + 4], regexExprForPt);

        auto ws = extractSubStr(infos[i + 4 + srf.dim_u], regexExprForNum);

        if (pts.size() != srf.dim_v) {
            printf("control points size error!\n");
            return;
        }
        for (int j = 0; j < srf.dim_v; j++) {
            auto pt = extractSubStr(pts[j], regexExprForNum);
            auto w = stod(ws[j]);
            for (int k = 0; k < 3; k++) {
                srf.vertex[(i * srf.dim_v + j) * srf.ptDim + k] = w * stod(pt[k]);
            }
            srf.vertex[(i * srf.dim_v + j) * srf.ptDim + 3] = w;
        }
    }


//    for (auto &s: res) {
//        cout << s << endl;
//    }


//    boost::smatch result;
//    std::string::const_iterator start = str.begin();
//    std::string::const_iterator end = str.end();
//
//    while(boost::regex_search(start, end, result, p)) {
//        std::cout << result[0] << std::endl;
//        start = result[0].second;
//        res.emplace_back(result[0].str());
//    }
}

// 使用boost提取str中匹配正则表达式的子串
vector<string> CaseReader::extractSubStr(const string &str, const string &regexExpr) {
    vector<string> res;
    boost::regex p(regexExpr);
    boost::sregex_token_iterator it(str.begin(), str.end(), p, 0);
    boost::sregex_token_iterator end;
    for (; it != end; ++it) {
        res.emplace_back(it->str());
    }
    return res;
}