//
// Created by uos on 2022/2/21.
//

#include "FsTab.h"
#include <QFile>
#include <QException>

FSTab::FSTab()
{

}

FSTab::~FSTab()
{

}

FSTabInfoList FSTab::getFSTabFromFile(const QString &filename)
{
    FSTabInfoList infos;
    QFile file(filename);
    if (!file.exists()) {
        return infos;
    }

    try {
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            return infos;
        }

        auto lines = file.readAll().split('\n');
        for (QString line : lines) {
            FSTabInfoPtr info(new FSTabInfo());
            infos.append(info);
            info->isComment = line.trimmed().startsWith("#");
            info->isEmptyLine = line.trimmed().isEmpty();

            if (info->isComment) {
                info->line = line;
            } else if (info->isEmptyLine) {
                info->line = "";
            } else {
                info->line = line;
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
                QStringList cols = line.replace("\t", " ").split(" ", Qt::SkipEmptyParts);
#else
                QStringList cols = line.replace("\t", " ").split(" ", QString::SkipEmptyParts);
#endif
                if (cols.size() != 6) {
                    continue;
                }
                int i = 0;
                for (QString &col: cols) {
                    switch (i++) {
                        case 0:
                            info->device = col;
                            break;
                        case 1:
                            info->mountPoint = col;
                            break;
                        case 2:
                            info->type = col;
                            break;
                        case 3:
                            info->options = col;
                            break;
                        case 4:
                            info->dump = col;
                            break;
                        case 5:
                            info->pass = col;
                            break;
                    }
                }
            }
        }
    } catch (QException &e) {
        file.close();
    }
    file.close();
    return infos;
}

QString FSTab::getDeviceUUID(const FSTabInfoPtr &fsTabInfo)
{
    if (fsTabInfo->device.startsWith("UUID=")) {
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
        auto list = fsTabInfo->device.split("=", Qt::SkipEmptyParts);
#else
        auto list = fsTabInfo->device.split("=", QString::SkipEmptyParts);
#endif
        if (list.size() == 2) {
            return list[1];
        }
    }
    return QString();
}

void FSTab::saveFSTab2File(FSTabInfoList &fstab, const QString &filename)
{

}

QString FSTab::subVolumeName(FSTabInfoPtr &fstabInfo)
{
    return QString();
}

bool FSTab::isSystemDirectory(const QString &uuid, const QString &dir)
{
    auto fsTabInfos = getFSTabFromFile(dir + "/etc/fstab");
    //没有找到fstab信息
    if (fsTabInfos.isEmpty()) {
        return false;
    }
    auto info = findFSTabByUUID(fsTabInfos, uuid);
    //fstab信息中没有指定的uuid
    if (info.isNull()) {
        return false;
    }

    return info->mountPoint == "/";
}

FSTabInfoPtr FSTab::findFSTabByMountPoint(const FSTabInfoList &fstab, const QString &mountPoint)
{
    for (auto &info : fstab) {
        if (info->isEmptyLine || info->isComment) {
            continue;
        }
        if (mountPoint == info->mountPoint) {
            return info;
        }
    }
    return FSTabInfoPtr();
}

FSTabInfoPtr FSTab::findFSTabByUUID(const FSTabInfoList &fstab, const QString &uuid)
{
    for (auto &info : fstab) {
        if (info->isEmptyLine || info->isComment) {
            continue;
        }
        if (getDeviceUUID(info) == uuid) {
            return info;
        }
    }
    return FSTabInfoPtr();
}

void FSTab::getFstabBindDir(const FSTabInfoList &fstabList, QMap<QString, QString> &bindDirMap)
{
    bindDirMap.clear();
    for (auto fstab : fstabList) {
        if (fstab->options.contains("bind")) {
            bindDirMap[fstab->mountPoint] = fstab->device + "/";
        }
    }
}

bool FSTab::isUuidInFstab(const QString &uuid, const FSTabInfoList &fstabList)
{
    for (auto &info : fstabList) {
        if (info->isEmptyLine || info->isComment || info->options.contains("bind")) {
            continue;
        }

        QString devUuid = FSTab::getDeviceUUID(info);
        if (uuid == devUuid) {
            return true;
        }
    }

    return false;
}

QStringList FSTab::getUuidListFromFstab(const FSTabInfoList &fstabList)
{
    QStringList uuidList;
    for (auto &info : fstabList) {
        if (info->isEmptyLine || info->isComment || info->options.contains("bind")) {
            continue;
        }

        QString devUuid = FSTab::getDeviceUUID(info);
        if (!devUuid.isEmpty()) {
            if (!uuidList.contains(devUuid)) {
                uuidList.append(devUuid);
            }
        }
    }

    return uuidList;
}
