#include "aptpackagebuilder.h"

#include "helpers.h"

namespace NApt {

AptPackageBuilder::InstallInformation AptPackageBuilder::calculateInstallInformation() const {
    IPackage::InstalledState installedState = IPackage::NOT_INSTALLED;
    QString installedVersion = "";
    QString availableVersion = "";
    // if installed state for the builder was already set to installed,
    // _version references the installed version
    if (_installedState == IPackage::INSTALLED) {
        installedVersion = _version.value_or("");
    } else if (_dpkgPackageInformation) {
        // if the installed state is set to "NOT_INSTALLED" _version references the available
        // version and we enrich the version information with that from the installedPackages map
        availableVersion = _version.value_or("");
        const map<string, const DpkgParser::PackageInformation>& installedPackages = *_dpkgPackageInformation;
        auto it = installedPackages.find(_name.value().toStdString());
        if (it != installedPackages.end()) {
            installedVersion = toQString(it->second.version);
            if (installedVersion == availableVersion)
                installedState = IPackage::INSTALLED;
            // else branch is not 100% exact, if installed version is *higher* then available
            // version it will also be displayed as Upgradable, but this should happen only
            // very rarely anyways
            else
                installedState = IPackage::UPGRADABLE;
        }
    }
    return InstallInformation {
        .installedState = installedState,
        .installedVersion = installedVersion,
        .availableVersion = availableVersion
    };
}


AptPackageBuilder AptPackageBuilder::fromPackageDetails(const PackageDetails& details) {
    AptPackageBuilder builder;
    builder.setEssential(details.essential());
    builder.setPriority(details.priority());
    builder.setSection(details.section());
    builder.setMaintainer(details.maintainer());
    builder.setReplaces(details.replaces());
    builder.setProvides(details.provides());
    builder.setPreDepends(details.preDepends());
    builder.setDepends(details.depends());
    builder.setRecommends(details.recommends());
    builder.setSuggests(details.suggests());
    builder.setConflicts(details.conflicts());
    builder.setBreaks(details.breaks());
    builder.setConffiles(details.conffiles());
    builder.setFilename(details.filename());
    builder.setSource(details.source());
    builder.setHomepage(details.homepage());
    builder.setSize(details.getSize());
    builder.setInstalledSize(details.getInstalledSize());
    return builder;
}

unique_ptr<Package> AptPackageBuilder::createPackage() const {
    auto installInformation = calculateInstallInformation();
    return make_unique<Package>(
        Package(
            _name.value(),
            _architecture.value_or(""),
            installInformation.availableVersion,
            installInformation.installedVersion,
            _description.value_or(""),
            installInformation.installedState
        )
    );
}

PackageDetails AptPackageBuilder::createPackageDetails() const {
    return PackageDetails(
        _description.value_or(""),
        _essential.value_or(""),
        _priority.value_or(""),
        _section.value_or(""),
        _maintainer.value_or(""),
        _replaces.value_or(""),
        _provides.value_or(""),
        _preDepends.value_or(""),
        _depends.value_or(""),
        _recommends.value_or(""),
        _suggests.value_or(""),
        _conflicts.value_or(""),
        _breaks.value_or(""),
        _md5sum.value_or(""),
        _conffiles.value_or(""),
        _filename.value_or(""),
        _source.value_or(""),
        _homepage.value_or(""),
        _size.value_or(0),
        _installedSize.value_or(0)
    );
}




void AptPackageBuilder::clear() {
    _name.reset();
    _essential.reset();
    _priority.reset();
    _section.reset();
    _installedSize.reset();
    _maintainer.reset();
    _architecture.reset();
    _source.reset();
    _version.reset();
    _replaces.reset();
    _provides.reset();
    _preDepends.reset();
    _depends.reset();
    _recommends.reset();
    _suggests.reset();
    _conflicts.reset();
    _breaks.reset();
    _filename.reset();
    _size.reset();
    _md5sum.reset();
    _conffiles.reset();
    _installedState.reset();
    _version.reset();
    _description.reset();
    _homepage.reset();
}

}
