// Squawk messenger. 
// Copyright (C) 2019  Yury Gubich <blue@macaw.me>
// 
// 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/>.

#include "info.h"

Shared::Info::Info(const QString& addr, EntryType tp):
    type(tp),
    address(addr),
    vcard(nullptr),
    activeKeys(nullptr),
    inactiveKeys(nullptr)
{
    switch (type) {
        case EntryType::none:
            break;
        case EntryType::contact:
        case EntryType::ownAccount:
            vcard = new VCard();
            activeKeys = new std::list<KeyInfo>();
            inactiveKeys = new std::list<KeyInfo>();
            break;
        default:
            throw 352;
    }
}

Shared::Info::Info():
    type(EntryType::none),
    address(""),
    vcard(nullptr),
    activeKeys(nullptr),
    inactiveKeys(nullptr)
{}

Shared::Info::Info(const Shared::Info& other):
    type(other.type),
    address(other.address),
    vcard(nullptr),
    activeKeys(nullptr),
    inactiveKeys(nullptr)
{
    switch (type) {
        case EntryType::none:
            break;
        case EntryType::contact:
        case EntryType::ownAccount:
            vcard = new VCard(other.getVCardRef());
            activeKeys = new std::list<KeyInfo>(other.getActiveKeysRef());
            inactiveKeys = new std::list<KeyInfo>(other.getInactiveKeysRef());
            break;
        default:
            throw 353;
    }
}

Shared::Info::~Info() {
    turnIntoNone();
}

void Shared::Info::turnIntoNone() {
    switch (type) {
        case EntryType::none:
            break;
        case EntryType::contact:
        case EntryType::ownAccount:
            delete vcard;
            vcard = nullptr;
            delete activeKeys;
            activeKeys = nullptr;
            delete inactiveKeys;
            inactiveKeys = nullptr;
            break;
        default:
            break;
    }
    type = EntryType::none;
}

void Shared::Info::turnIntoContact(
    const Shared::VCard& crd,
    const std::list<KeyInfo>& aks,
    const std::list<KeyInfo>& iaks
) {
    switch (type) {
        case EntryType::none:
            vcard = new VCard(crd);
            activeKeys = new std::list<KeyInfo>(aks);
            inactiveKeys = new std::list<KeyInfo>(iaks);
            break;
        case EntryType::contact:
        case EntryType::ownAccount:
            *vcard = crd;
            *activeKeys = aks;
            *inactiveKeys = iaks;
            break;
        default:
            break;
    }

    type = EntryType::contact;
}

void Shared::Info::turnIntoContact(
    Shared::VCard* crd,
    std::list<KeyInfo>* aks,
    std::list<KeyInfo>* iaks
) {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            delete vcard;
            delete activeKeys;
            delete inactiveKeys;
            [[fallthrough]];
        case EntryType::none:
            vcard = crd;
            activeKeys = aks;
            inactiveKeys = iaks;
            break;
        default:
            break;
    }

    type = EntryType::contact;
}

void Shared::Info::turnIntoOwnAccount(
    const Shared::VCard& crd,
    const std::list<KeyInfo>& aks,
    const std::list<KeyInfo>& iaks
) {
        switch (type) {
        case EntryType::none:
            vcard = new VCard(crd);
            activeKeys = new std::list<KeyInfo>(aks);
            inactiveKeys = new std::list<KeyInfo>(iaks);
            break;
        case EntryType::contact:
        case EntryType::ownAccount:
            *vcard = crd;
            *activeKeys = aks;
            *inactiveKeys = iaks;
            break;
        default:
            break;
    }

    type = EntryType::ownAccount;
}

void Shared::Info::turnIntoOwnAccount(
    Shared::VCard* crd,
    std::list<KeyInfo>* aks,
    std::list<KeyInfo>* iaks
) {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            delete vcard;
            delete activeKeys;
            delete inactiveKeys;
            [[fallthrough]];
        case EntryType::none:
            vcard = crd;
            activeKeys = aks;
            inactiveKeys = iaks;
            break;
        default:
            break;
    }

    type = EntryType::ownAccount;
}

void Shared::Info::setAddress(const QString& addr) {
    address = addr;}

QString Shared::Info::getAddress() const {
    return address;}

const QString& Shared::Info::getAddressRef() const {
    return address;}

Shared::EntryType Shared::Info::getType() const {
    return type;}

std::list<Shared::KeyInfo> & Shared::Info::getActiveKeysRef() {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return *activeKeys;
            break;
        default:
            throw 354;
    }
}

const std::list<Shared::KeyInfo> & Shared::Info::getActiveKeysRef() const {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return *activeKeys;
            break;
        default:
            throw 355;
    }
}

std::list<Shared::KeyInfo>* Shared::Info::getActiveKeys() {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return activeKeys;
            break;
        default:
            throw 356;
    }
}

const std::list<Shared::KeyInfo>* Shared::Info::getActiveKeys() const {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return activeKeys;
            break;
        default:
            throw 357;
    }
}

std::list<Shared::KeyInfo> & Shared::Info::getInactiveKeysRef() {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return *inactiveKeys;
            break;
        default:
            throw 358;
    }
}

const std::list<Shared::KeyInfo> & Shared::Info::getInactiveKeysRef() const {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return *inactiveKeys;
            break;
        default:
            throw 359;
    }
}

std::list<Shared::KeyInfo>* Shared::Info::getInactiveKeys() {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return inactiveKeys;
            break;
        default:
            throw 360;
    }
}

const std::list<Shared::KeyInfo>* Shared::Info::getInactiveKeys() const {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return inactiveKeys;
            break;
        default:
            throw 361;
    }
}

const Shared::VCard & Shared::Info::getVCardRef() const {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return *vcard;
            break;
        default:
            throw 362;
    }
}

Shared::VCard & Shared::Info::getVCardRef()  {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return *vcard;
            break;
        default:
            throw 363;
    }
}

const Shared::VCard * Shared::Info::getVCard() const {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return vcard;
            break;
        default:
            throw 364;
    }
}

Shared::VCard * Shared::Info::getVCard() {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            return vcard;
            break;
        default:
            throw 365;
    }
}

void Shared::Info::setActiveKeys(std::list<KeyInfo>* keys) {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            activeKeys = keys;
            break;
        default:
            throw 366;
    }
}

void Shared::Info::setVCard(Shared::VCard* card) {
    switch (type) {
        case EntryType::contact:
        case EntryType::ownAccount:
            vcard = card;
            break;
        default:
            throw 367;
    }
}