/*
 * Copyright (C) 2016 Canonical Ltd
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: James Henstridge <james.henstridge@canonical.com>
 */

#include <lomiri/storage/provider/internal/TestServerImpl.h>
#include <lomiri/storage/internal/InactivityTimer.h>
#include <lomiri/storage/provider/Exceptions.h>
#include <lomiri/storage/provider/ProviderBase.h>
#include <lomiri/storage/provider/internal/DBusPeerCache.h>
#include <lomiri/storage/provider/internal/FixedAccountData.h>
#include <lomiri/storage/provider/internal/OnlineAccountData.h>
#include <lomiri/storage/provider/internal/ProviderInterface.h>
#include <lomiri/storage/provider/internal/dbusmarshal.h>
#include "provideradaptor.h"

#include <LomiriOnlineAccountsQt/Account>

#include <stdexcept>

using namespace std;
using lomiri::storage::internal::InactivityTimer;

namespace
{
constexpr int TIMEOUT = 30000;
}

namespace lomiri
{
namespace storage
{
namespace provider
{
namespace internal
{

TestServerImpl::TestServerImpl(shared_ptr<ProviderBase> const& provider,
                               OnlineAccounts::Account* account,
                               QDBusConnection const& connection,
                               string const& object_path)
    : connection_(connection), object_path_(object_path),
      inactivity_timer_(make_shared<InactivityTimer>(TIMEOUT))
{
    qRegisterMetaType<std::exception_ptr>();
    qDBusRegisterMetaType<Item>();
    qDBusRegisterMetaType<std::vector<Item>>();

    auto peer_cache = make_shared<DBusPeerCache>(connection_);
    shared_ptr<AccountData> account_data;
    if (account)
    {
        account_data = make_shared<OnlineAccountData>(
            provider, peer_cache, inactivity_timer_, connection_, account);
    }
    else
    {
        account_data = make_shared<FixedAccountData>(
            provider, peer_cache, inactivity_timer_, connection_);
    }
    interface_.reset(new ProviderInterface(account_data));
    new ProviderAdaptor(interface_.get());

    if (!connection_.registerObject(QString::fromStdString(object_path_),
                                    interface_.get()))
    {
        string msg = "Could not register provider on connection: " + connection_.lastError().message().toStdString();
        throw ResourceException(msg, int(connection_.lastError().type()));
    }
}

TestServerImpl::~TestServerImpl()
{
    connection_.unregisterObject(QString::fromStdString(object_path_));
}

QDBusConnection const& TestServerImpl::connection() const
{
    return connection_;
}

string const& TestServerImpl::object_path() const
{
    return object_path_;
}

}
}
}
}
