/*
 * Copyright (C) 2014-2024 CZ.NIC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#include <QMap>
#include <QStringList>

#include "src/datovka_shared/isds/message_attachment.h"

/*
 * Suffixes listed in pril_2/WS_manipulace_s_datovymi_zpravami.pdf, section 3.
 *
 * Maps suffix name onto MIME type. First MIME type in list is preferred.
 */
static const QMap<QString, QStringList> suffixToMimeTypes =
    {
        {"asice", {"application/vnd.etsi.asic-e+zip"}},
        {"asics", {"application/vnd.etsi.asic-s+zip"}},
        {"cer", {"application/x-x509-ca-cert"}},
        {"crt", {"application/x-x509-ca-cert"}},
        {"csv", {"text/csv"}},
        {"der", {"application/x-x509-ca-cert"}},
        {"doc", {"application/msword"}},
        {"docx", {"application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/encrypted"}},
        {"dbf", {"application/octet-stream"}},
        {"dgn", {"application/octet-stream"}},
        {"dwg", {"image/vnd.dwg"}},
        {"edi", {"application/edifact", "application/edi-x12", "application/edi-consent", "text/plain", "text/xml", "application/xml"}},
        {"fo", {"application/vnd.software602.filler.form+xml", "application/xml"}},
        {"gfs", {"application/xml", "text/xml"}},
        {"gif", {"image/gif"}},
        {"gml", {"application/xml", "text/xml"}},
        {"heic", {"image/heic", "image/heic-sequence"}},
        {"heif", {"image/heif", "image/heif-sequence"}},
        {"html", {"text/html"}},
        {"htm", {"text/html"}},
        {"isdoc", {"text/isdoc"}},
        {"isdocx", {"text/isdocx"}},
        {"jfif", {"image/jpeg", "image/pjpeg"}},
        {"jpeg", {"image/jpeg", "image/pjpeg"}},
        {"jpg", {"image/jpeg", "image/pjpeg"}},
        {"json", {"application/json"}},
        {"mpeg", {"video/mpeg", "video/mpeg1", "video/mpeg2", "video/mpg"}},
        {"mpeg1", {"video/mpeg", "video/mpeg1", "video/mpeg2", "video/mpg"}},
        {"mpeg2", {"video/mpeg", "video/mpeg1", "video/mpeg2", "video/mpg"}},
        {"mpg", {"video/mpeg", "video/mpeg1", "video/mpeg2", "video/mpg"}},
        {"mp2", {"audio/mpeg"}},
        {"mp3", {"audio/mpeg"}},
        {"mp4", {"audio/mp4", "video/mp4"}},
        {"m4a", {"audio/mp4"}},
        {"m4p", {"audio/mp4", "video/mp4"}},
        {"m4v", {"video/mp4"}},
        {"odp", {"application/vnd.oasis.opendocument.presentation"}},
        {"ods", {"application/vnd.oasis.opendocument.spreadsheet"}},
        {"odt", {"application/vnd.oasis.opendocument.text"}},
        {"pdf", {"application/pdf"}},
        {"pk7", {"application/pkcs7-mime", "application/x-pkcs7-mime"}},
        {"png", {"image/png", "image/x-png"}},
        {"ppt", {"application/vnd.ms-powerpoint"}},
        {"pptx", {"application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/encrypted"}},
        {"prj", {"application/octet-stream"}},
        {"p7b", {"application/pkcs7-certificates", "application/pkcs7-mime", "application/x-pkcs7-certificates"}},
        {"p7c", {"application/pkcs7-mime", "application/x-pkcs7-mime"}},
        {"p7f", {"application/pkcs7-signature"}},
        {"p7m", {"application/pkcs7-mime", "application/x-pkcs7-mime"}},
        {"p7s", {"application/pkcs7-signature", "application/x-pkcs7-signature"}},
        {"qix", {"application/octet-stream"}},
        {"rtf", {"application/msword", "text/rtf", "application/rtf"}},
        {"sbn", {"application/octet-stream"}},
        {"sbx", {"application/octet-stream"}},
        {"sce", {"application/vnd.etsi.asic-e+zip"}},
        {"scs", {"application/vnd.etsi.asic-s+zip"}},
        {"shp", {"application/octet-stream"}},
        {"shx", {"application/octet-stream"}},
        {"tiff", {"image/tiff"}},
        {"tif", {"image/tiff"}},
        {"tst", {"application/timestamp-reply"}},
        {"tsr", {"application/timestamp-reply"}},
        {"txt", {"text/plain"}},
        {"wav", {"audio/wav", "audio/wave", "audio/x-wav"}},
        {"xls", {"application/vnd.ms-excel"}},
        {"xlsx", {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/encrypted"}},
        {"xml", {"application/xml", "text/xml"}},
        {"xsd", {"application/xml", "text/xml"}},
        {"zfo", {"application/vnd.software602.filler.form-xml-zip"}},
        {"zip", {"application/zip", "application/x-compressed", "application/x-zip-compressed"}}
    };

/*!
 * @brief Get a set of map keys.
 *
 * @param[in] map Input map.
 * @return Set of keys.
 */
QSet<QString> getKeySet(const QMap<QString, QStringList> &map)
{
	const QList<QString> keys = map.keys();
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
	return QSet<QString>(keys.begin(), keys.end());
#else /* < Qt-5.14.0 */
	return keys.toSet();
#endif /* >= Qt-5.14.0 */
}

const QSet<QString> &Isds::Attachment::allowedFileSuffixes(void)
{
	static const QSet<QString> listedSuffixes =
	    getKeySet(suffixToMimeTypes);

	return listedSuffixes;
}

const QSet<QString> Isds::Attachment::expectedMimeTypeNamesForSuffix(
    const QString &suffix)
{
	const QString lowerCaseSuffix = suffix.toLower();

	if (Q_UNLIKELY(!suffixToMimeTypes.contains(lowerCaseSuffix))) {
		return QSet<QString>();
	}

	const QStringList mimeTypeList = suffixToMimeTypes[lowerCaseSuffix];

#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
	return QSet<QString>(mimeTypeList.begin(), mimeTypeList.end());
#else /* < Qt-5.14.0 */
	return mimeTypeList.toSet();
#endif /* >= Qt-5.14.0 */
}

const QString Isds::Attachment::suggestedMimeTypeName(const QString &suffix)
{
	const QString lowerCaseSuffix = suffix.toLower();

	if (Q_UNLIKELY(!suffixToMimeTypes.contains(lowerCaseSuffix))) {
		return QString();
	}

	return suffixToMimeTypes[suffix].value(0, QString());
}
