/*
    This file is part of the KContacts framework.
    Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "addresstest.h"
#include "addresseelist.h"
#include "vcardtool_p.h"
#include "kcontacts/address.h"
#include <kconfig.h>
#include <kconfiggroup.h>
#include <QTest>
#include <QStandardPaths>

QTEST_MAIN(AddressTest)
#ifndef Q_OS_WIN
void initLocale()
{
    qputenv("LC_ALL", "it_CH.utf-8");
}

Q_CONSTRUCTOR_FUNCTION(initLocale)
#endif

void AddressTest::initTestCase()
{
}

void AddressTest::emptyTest()
{
    KContacts::Address address;

    QVERIFY(address.isEmpty());
}

void AddressTest::storeTest()
{
    KContacts::Address address;

    address.setId(QStringLiteral("My Id"));
    address.setType(KContacts::Address::Home);
    address.setPostOfficeBox(QStringLiteral("1234"));
    address.setExtended(QStringLiteral("My Extended Label"));
    address.setStreet(QStringLiteral("My Street"));
    address.setLocality(QStringLiteral("My Locality"));
    address.setRegion(QStringLiteral("My Region"));
    address.setPostalCode(QStringLiteral("My PostalCode"));
    address.setCountry(QStringLiteral("My Country"));
    address.setLabel(QStringLiteral("My Label"));

    QCOMPARE(address.id(), QStringLiteral("My Id"));
    QCOMPARE(address.type(), KContacts::Address::Home);
    QCOMPARE(address.postOfficeBox(), QStringLiteral("1234"));
    QCOMPARE(address.extended(), QStringLiteral("My Extended Label"));
    QCOMPARE(address.street(), QStringLiteral("My Street"));
    QCOMPARE(address.locality(), QStringLiteral("My Locality"));
    QCOMPARE(address.region(), QStringLiteral("My Region"));
    QCOMPARE(address.postalCode(), QStringLiteral("My PostalCode"));
    QCOMPARE(address.country(), QStringLiteral("My Country"));
    QCOMPARE(address.label(), QStringLiteral("My Label"));
    QVERIFY(!address.geo().isValid());
}

void AddressTest::equalsTest()
{
    KContacts::Address address1, address2;

    address1.setId(QStringLiteral("My Id"));
    address1.setType(KContacts::Address::Home);
    address1.setPostOfficeBox(QStringLiteral("1234"));
    address1.setExtended(QStringLiteral("My Extended Label"));
    address1.setStreet(QStringLiteral("My Street"));
    address1.setLocality(QStringLiteral("My Locality"));
    address1.setRegion(QStringLiteral("My Region"));
    address1.setPostalCode(QStringLiteral("My Postalcode"));
    address1.setCountry(QStringLiteral("My country"));
    address1.setLabel(QStringLiteral("My Label"));

    address2.setId(QStringLiteral("My Id"));
    address2.setType(KContacts::Address::Home);
    address2.setPostOfficeBox(QStringLiteral("1234"));
    address2.setExtended(QStringLiteral("My Extended Label"));
    address2.setStreet(QStringLiteral("My Street"));
    address2.setLocality(QStringLiteral("My Locality"));
    address2.setRegion(QStringLiteral("My Region"));
    address2.setPostalCode(QStringLiteral("My Postalcode"));
    address2.setCountry(QStringLiteral("My country"));
    address2.setLabel(QStringLiteral("My Label"));

    QVERIFY(address1 == address2);
}

void AddressTest::differsTest()
{
    KContacts::Address address1(KContacts::Address::Home);
    KContacts::Address address2(KContacts::Address::Work);

    QVERIFY(address1 != address2);
}

void AddressTest::assignmentTest()
{
    KContacts::Address address1, address2;

    address1.setId(QStringLiteral("My Id"));
    address1.setType(KContacts::Address::Home);
    address1.setPostOfficeBox(QStringLiteral("1234"));
    address1.setExtended(QStringLiteral("My Extended Label"));
    address1.setStreet(QStringLiteral("My Street"));
    address1.setLocality(QStringLiteral("My Locality"));
    address1.setRegion(QStringLiteral("My Region"));
    address1.setPostalCode(QStringLiteral("My Postalcode"));
    address1.setCountry(QStringLiteral("My country"));
    address1.setLabel(QStringLiteral("My Label"));

    address2 = address1;

    QVERIFY(address1 == address2);
}

void AddressTest::serializeTest()
{
    KContacts::Address address1, address2;

    address1.setType(KContacts::Address::Work);
    address1.setPostOfficeBox(QStringLiteral("1234"));
    address1.setExtended(QStringLiteral("My Extended Label"));
    address1.setStreet(QStringLiteral("My Street"));
    address1.setLocality(QStringLiteral("My Locality"));
    address1.setRegion(QStringLiteral("My Region"));
    address1.setPostalCode(QStringLiteral("My Postalcode"));
    address1.setCountry(QStringLiteral("My country"));
    address1.setLabel(QStringLiteral("My Label"));

    QByteArray data;
    QDataStream s(&data, QIODevice::WriteOnly);
    s << address1;

    QDataStream t(&data, QIODevice::ReadOnly);
    t >> address2;

    QVERIFY(address1 == address2);
}

void AddressTest::formatTest()
{
    {
        KContacts::Address address;
        address.setStreet(QStringLiteral("Lummerlandstr. 1"));
        address.setPostalCode(QStringLiteral("12345"));
        address.setLocality(QStringLiteral("Lummerstadt"));
        address.setCountry(QStringLiteral("Germany"));

        const QString result(QStringLiteral("Jim Knopf\nLummerlandstr. 1\n"
                                            "12345 Lummerstadt\n\nGERMANY"));

        QCOMPARE(address.formattedAddress(QStringLiteral("Jim Knopf")), result);
    }

    {
        KContacts::Address address;
        address.setStreet(QStringLiteral("457 Foobar Ave"));
        address.setPostalCode(QStringLiteral("1A2B3C"));
        address.setLocality(QStringLiteral("Nervousbreaktown"));
        address.setRegion(QStringLiteral("DC"));
        address.setCountry(QStringLiteral("United States of America"));

        const QString result(
            QStringLiteral("Huck Finn\n457 Foobar Ave\nNervousbreaktown,"
                           "  DC 1A2B3C\n\nUNITED STATES OF AMERICA"));
        QCOMPARE(address.formattedAddress(QStringLiteral("Huck Finn")), result);
    }

    {
        KContacts::Address address;
        address.setStreet(QStringLiteral("Lummerlandstr. 1"));
        address.setPostalCode(QStringLiteral("12345"));
        address.setLocality(QStringLiteral("Lummerstadt"));
        address.setCountry(QStringLiteral("Deutschland"));

        const QString result(QStringLiteral("Jim Knopf\nLummerlandstr. 1\n"
                                            "12345 Lummerstadt\n\nDEUTSCHLAND"));

        QCOMPARE(address.formattedAddress(QStringLiteral("Jim Knopf")), result);
    }

    {
        KContacts::Address address;
        address.setStreet(QStringLiteral("Lummerlandstr. 1"));
        address.setPostalCode(QStringLiteral("12345"));
        address.setLocality(QStringLiteral("Lummerstadt"));
        address.setCountry(QString());

        const QString result(QStringLiteral("Jim Knopf\nLummerlandstr. 1\n12345 Lummerstadt"));

        QCOMPARE(address.formattedAddress(QStringLiteral("Jim Knopf")), result);
    }

    {
        KContacts::Address address;
        address.setStreet(QStringLiteral("Haus Randa"));
        address.setPostalCode(QStringLiteral("1234"));
        address.setLocality(QStringLiteral("Randa"));
        address.setPostOfficeBox(QStringLiteral("5678"));
        address.setCountry(QStringLiteral("Schweiz"));

        // we want the Italian variant of the Swiss format for it_CH
        const QString result(QStringLiteral("Dr. Konqui\nCasella postale 5678\nHaus Randa\n1234 Randa\n\nSCHWEIZ"));

        QCOMPARE(address.formattedAddress(QStringLiteral("Dr. Konqui")), result);
    }
}

void AddressTest::shouldExportVcard3()
{
    KContacts::Address address;

    address.setId(QStringLiteral("My Id"));
    address.setType(KContacts::Address::Home);
    address.setPostOfficeBox(QStringLiteral("1234"));
    address.setExtended(QStringLiteral("My Extended Label"));
    address.setStreet(QStringLiteral("My Street"));
    address.setLocality(QStringLiteral("My Locality"));
    address.setRegion(QStringLiteral("My Region"));
    address.setPostalCode(QStringLiteral("My Postalcode"));
    address.setCountry(QStringLiteral("My country"));
    address.setLabel(QStringLiteral("My Label"));

    KContacts::AddresseeList lst;
    KContacts::Addressee addr;
    addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
    addr.setUid(QStringLiteral("testuid"));
    addr.insertAddress(address);
    lst << addr;

    KContacts::VCardTool vcard;
    const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
    QByteArray expected("BEGIN:VCARD\r\n"
                        "VERSION:3.0\r\n"
                        "ADR;TYPE=home:1234;My Extended Label;My Street;My Locality;My Region;My Pos\r\n"
                        " talcode;My country\r\n"
                        "EMAIL:foo@kde.org\r\n"
                        "LABEL;TYPE=home:My Label\r\n"
                        "N:;;;;\r\n"
                        "UID:testuid\r\n"
                        "END:VCARD\r\n\r\n");
    QCOMPARE(ba, expected);
}

void AddressTest::shouldParseAddressVCard3()
{
    QByteArray vcarddata("BEGIN:VCARD\n"
                         "VERSION:3.0\n"
                         "N:LastName;FirstName;;;\n"
                         "ADR;TYPE=home:1234;My Extended Label;My Street;My Locality;My Region;My Pos\r\n"
                         " talcode;My country\r\n"
                         "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
                         "LABEL;TYPE=home:My Label\r\n"
                         "REV:2015-03-14T09:24:45+00:00\n"
                         "FN:FirstName LastName\n"
                         "END:VCARD\n");

    KContacts::VCardTool vcard;
    const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
    QCOMPARE(lst.count(), 1);
    QCOMPARE(lst.at(0).addresses().count(), 1);
    KContacts::Address address = lst.at(0).addresses().at(0);
    QCOMPARE(address.type(), KContacts::Address::Home);
    QCOMPARE(address.postOfficeBox(), QStringLiteral("1234"));
    QCOMPARE(address.extended(), QStringLiteral("My Extended Label"));
    QCOMPARE(address.region(), QStringLiteral("My Region"));
    QCOMPARE(address.street(), QStringLiteral("My Street"));
    QCOMPARE(address.country(), QStringLiteral("My country"));
    QCOMPARE(address.postalCode(), QStringLiteral("My Postalcode"));
    QCOMPARE(address.label(), QStringLiteral("My Label"));
}

void AddressTest::shouldParseAddressVCard4()
{
    QByteArray vcarddata("BEGIN:VCARD\r\n"
                         "VERSION:4.0\r\n"
                         "ADR;LABEL=\"My Label\";TYPE=home:1234;My Extended Label;My Street;My Locality\r\n"
                         " ;My Region;My Postalcode;My country\r\nEMAIL:foo@kde.org\r\n"
                         "N:;;;;\r\n"
                         "UID:testuid\r\n"
                         "END:VCARD\r\n\r\n");
    KContacts::VCardTool vcard;
    const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
    QCOMPARE(lst.count(), 1);
    QCOMPARE(lst.at(0).addresses().count(), 1);
    KContacts::Address address = lst.at(0).addresses().at(0);
    QCOMPARE(address.type(), KContacts::Address::Home);
    QCOMPARE(address.postOfficeBox(), QStringLiteral("1234"));
    QCOMPARE(address.extended(), QStringLiteral("My Extended Label"));
    QCOMPARE(address.region(), QStringLiteral("My Region"));
    QCOMPARE(address.street(), QStringLiteral("My Street"));
    QCOMPARE(address.country(), QStringLiteral("My country"));
    QCOMPARE(address.postalCode(), QStringLiteral("My Postalcode"));
    QCOMPARE(address.label(), QStringLiteral("My Label"));
}

void AddressTest::shouldParseAddressVCard4WithGeoPosition()
{
    QByteArray vcarddata("BEGIN:VCARD\r\n"
                         "VERSION:4.0\r\n"
                         "ADR;GEO=\"geo:22.500000,45.099998\";LABEL=\"My Label\";TYPE=home:1234;My Extend\r\n"
                         " ed Label;My Street;My Locality;My Region;My Postalcode;My country\r\n"
                         "EMAIL:foo@kde.org\r\n"
                         "N:;;;;\r\n"
                         "UID:testuid\r\n"
                         "END:VCARD\r\n\r\n");
    KContacts::VCardTool vcard;
    const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
    QCOMPARE(lst.count(), 1);
    QCOMPARE(lst.at(0).addresses().count(), 1);
    KContacts::Address address = lst.at(0).addresses().at(0);
    QCOMPARE(address.type(), KContacts::Address::Home);
    QCOMPARE(address.postOfficeBox(), QStringLiteral("1234"));
    QCOMPARE(address.extended(), QStringLiteral("My Extended Label"));
    QCOMPARE(address.region(), QStringLiteral("My Region"));
    QCOMPARE(address.street(), QStringLiteral("My Street"));
    QCOMPARE(address.country(), QStringLiteral("My country"));
    QCOMPARE(address.postalCode(), QStringLiteral("My Postalcode"));
    QCOMPARE(address.label(), QStringLiteral("My Label"));
    KContacts::Geo geo = address.geo();
    QVERIFY(geo.isValid());
    QCOMPARE(geo.latitude(), 22.5f);
    QCOMPARE(geo.longitude(), 45.1f);
}

void AddressTest::shouldExportVCard4WithGeoPosition()
{
    KContacts::Address address;

    address.setId(QStringLiteral("My Id"));
    address.setType(KContacts::Address::Home);
    address.setPostOfficeBox(QStringLiteral("1234"));
    address.setExtended(QStringLiteral("My Extended Label"));
    address.setStreet(QStringLiteral("My Street"));
    address.setLocality(QStringLiteral("My Locality"));
    address.setRegion(QStringLiteral("My Region"));
    address.setPostalCode(QStringLiteral("My Postalcode"));
    address.setCountry(QStringLiteral("My country"));
    address.setLabel(QStringLiteral("My Label"));

    KContacts::Geo geo;

    geo.setLatitude(22.5f);
    geo.setLongitude(45.1f);
    address.setGeo(geo);

    KContacts::AddresseeList lst;
    KContacts::Addressee addr;
    addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
    addr.setUid(QStringLiteral("testuid"));
    addr.insertAddress(address);
    lst << addr;

    KContacts::VCardTool vcard;
    const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
    QByteArray expected("BEGIN:VCARD\r\n"
                        "VERSION:4.0\r\n"
                        "ADR;GEO=\"geo:22.500000,45.099998\";LABEL=\"My Label\";TYPE=home:1234;My Extend\r\n"
                        " ed Label;My Street;My Locality;My Region;My Postalcode;My country\r\n"
                        "EMAIL:foo@kde.org\r\n"
                        "N:;;;;\r\n"
                        "UID:testuid\r\n"
                        "END:VCARD\r\n\r\n");
    QCOMPARE(ba, expected);
}

void AddressTest::shouldExportVcard4()
{
    KContacts::Address address;

    address.setId(QStringLiteral("My Id"));
    address.setType(KContacts::Address::Home);
    address.setPostOfficeBox(QStringLiteral("1234"));
    address.setExtended(QStringLiteral("My Extended Label"));
    address.setStreet(QStringLiteral("My Street"));
    address.setLocality(QStringLiteral("My Locality"));
    address.setRegion(QStringLiteral("My Region"));
    address.setPostalCode(QStringLiteral("My Postalcode"));
    address.setCountry(QStringLiteral("My country"));
    address.setLabel(QStringLiteral("My Label"));

    KContacts::AddresseeList lst;
    KContacts::Addressee addr;
    addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
    addr.setUid(QStringLiteral("testuid"));
    addr.insertAddress(address);
    lst << addr;

    KContacts::VCardTool vcard;
    const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
    QByteArray expected("BEGIN:VCARD\r\n"
                        "VERSION:4.0\r\n"
                        "ADR;LABEL=\"My Label\";TYPE=home:1234;My Extended Label;My Street;My Locality\r\n"
                        " ;My Region;My Postalcode;My country\r\nEMAIL:foo@kde.org\r\n"
                        "N:;;;;\r\n"
                        "UID:testuid\r\n"
                        "END:VCARD\r\n\r\n");
    QCOMPARE(ba, expected);
}

void AddressTest::countryToISOTest()
{
    using namespace KContacts;
    QCOMPARE(Address::countryToISO(QStringLiteral("France")), QLatin1String("fr"));
    QCOMPARE(Address::countryToISO(QStringLiteral("Frankreich")), QLatin1String("fr"));
    QCOMPARE(Address::countryToISO(QStringLiteral("Germany")), QLatin1String("de"));
    QCOMPARE(Address::countryToISO(QStringLiteral("Österreich")), QLatin1String("at"));
    QCOMPARE(Address::countryToISO(QStringLiteral("Disneyland")), QString());
    QCOMPARE(Address::countryToISO(QStringLiteral("Østrig")), QLatin1String("at"));
    QCOMPARE(Address::countryToISO(QStringLiteral("Den Demokratiske Republik Congo (DRC)")), QLatin1String("cd"));
    QCOMPARE(Address::countryToISO(QStringLiteral("Congo-Kinshasa")), QLatin1String("cd"));
    QCOMPARE(Address::countryToISO(QStringLiteral("South Sudan")), QLatin1String("ss"));
    QCOMPARE(Address::countryToISO(QStringLiteral("United States")), QLatin1String("us"));
    QCOMPARE(Address::countryToISO(QStringLiteral("United States Of America")), QLatin1String("us"));
    QCOMPARE(Address::countryToISO(QStringLiteral("United")), QString());
    QCOMPARE(Address::countryToISO(QStringLiteral("대한민국")), QLatin1String("kr"));

    QCOMPARE(Address::countryToISO(QStringLiteral("Osterreich")), QLatin1String("at"));
    QCOMPARE(Address::countryToISO(QStringLiteral("Ünited  States\nOf America")), QLatin1String("us"));
}

void AddressTest::isoToCountryTest()
{
    qunsetenv("LC_ALL");
    qputenv("LANGUAGE", "en");

    using namespace KContacts;
    QCOMPARE(Address::ISOtoCountry(QStringLiteral("FR")), QLatin1String("France"));
    QCOMPARE(Address::ISOtoCountry(QStringLiteral("de")), QLatin1String("Germany"));

    // invalid
    QCOMPARE(Address::ISOtoCountry(QStringLiteral("EU")), QLatin1String("EU"));
    QCOMPARE(Address::ISOtoCountry(QStringLiteral("zz")), QLatin1String("zz"));
    QCOMPARE(Address::ISOtoCountry(QStringLiteral("0")), QLatin1String("0"));
}
