/*
 * 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 (Info&& other):
    type(other.type),
    address(other.address),
    vcard(other.vcard),
    activeKeys(other.activeKeys),
    inactiveKeys(other.inactiveKeys)
{
    other.type = EntryType::none;
}

Shared::Info& Shared::Info::operator = (Info&& other) {
    type = other.type;
    address = other.address;
    vcard = other.vcard;
    activeKeys = other.activeKeys;
    inactiveKeys = other.inactiveKeys;
    other.type = EntryType::none;
    return *this;
}

Shared::Info& Shared::Info::operator = (const Info& other) {
    type = other.type;
    address = other.address;
    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 351;
    }
    return *this;
}

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;
    }
}