/*
 * BSD 2-Clause License
 *
 * Copyright (c) 2020, Agnieszka Cicha-Cisek
 * Copyright (c) 2020, Patryk Cisek
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <chrono>
#include <iostream>
#include <memory>

#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>

#include <QApplication>
#include <QDateTime>

#include "authenticatedialog.h"
#include "authentication.h"
#include "nitrokeyimpl.h"
#include "mainwindow.h"
#include "newtotpslotdialog.h"
#include "totpuriparser.h"

/**
 * @file
 * Nitrokey Authenticator application
 *
 * @mainpage
 *
 * @section What is Nitrokey Authenticator
 * Nitrokey Authenticator is a drop-in replacement for
 * authenticator applications like
 * <a href="https://www.google-authenticator.com/">
 * Google Authenticator</a>, <a href="https://authy.com/">
 * Authy</a> and alike. The significant difference between
 * Nitrokey Authenticator and others is, that the secret
 * used to generate 1-time authentication codes is stored
 * inside <a href="https://puri.sm/products/librem-key/">
 * Nitrokey</a> (inside the USB key). This secret, once
 * stored inside the key, never leaves it again. Whenever
 * you're generating the code, the application requests
 * the key to generate it. The cryptographic operation of
 * generating the code is executed by the key.
 *
 * Another words, compromising your system would not be enough
 * to steal the secret(s) used for 2nd-factor-authentication.
 * Attacker would also have to hack Nitrokey.
 */

int main(int argc, char *argv[])
{
    constexpr int SESSION_TIMEOUT_MSEC = 5 * 60 * 1000;
    QApplication a(argc, argv);
    boost::log::core::get()->set_filter
    (
        boost::log::trivial::severity >= boost::log::trivial::debug
    );

    qRegisterMetaType<QList<TOTPSlot>>();
    qRegisterMetaType<GetTOTPCodeResponse>();
    std::shared_ptr<NitrokeyBase> nitrokey(new NitrokeyImpl(5));
    std::shared_ptr<NitrokeyProvider> nitrokeyProvider(new NitrokeyProvider(nitrokey));

    std::shared_ptr<AuthenticateDialog> adminAuthenticateDialog(
                new AuthenticateDialog(AuthenticateDialog::Type::ADMIN));
    std::shared_ptr<Authentication> adminAuthentication(
                new Authentication(adminAuthenticateDialog, nitrokeyProvider, SESSION_TIMEOUT_MSEC));

    std::shared_ptr<AuthenticateDialog> userAuthenticateDialog(
                new AuthenticateDialog(AuthenticateDialog::Type::USER));
    std::shared_ptr<Authentication> userAuthentication(
                new Authentication(userAuthenticateDialog, nitrokeyProvider, SESSION_TIMEOUT_MSEC));

    std::shared_ptr<NewTOTPSlotDialog> newTOTOSlotDialog(new NewTOTPSlotDialog());
    std::shared_ptr<KeyTOTPModel> totpSlotsModel(new KeyTOTPModel(nitrokeyProvider,
                                                                  adminAuthenticateDialog,
                                                                  adminAuthentication,
                                                                  userAuthenticateDialog,
                                                                  userAuthentication,
                                                                  newTOTOSlotDialog));
    MainWindow w(totpSlotsModel);
    w.show();
    a.setQuitOnLastWindowClosed(true);
    a.exec();
}
