/*
 * This file is part of the PolKit-tqt project
 * Copyright (C) 2009 Radek Novacek <rnovacek@redhat.com>
 *
 * 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.
 */

#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
#include <polkitagent/polkitagent.h>

#include "polkit-tqt-identity.h"
#include "polkit-tqt-agent-session.h"

#include <tqstring.h>


using namespace PolkitTQt;
using namespace PolkitTQt::Agent;

//--------------------------------------
// Session::Private
//--------------------------------------

class Session::Private
{
  public:
    Private()
    {
    }

    ~Private()
    {
      // polkitAgentSession is freed in Session d'tor
    }

    static void completed(PolkitAgentSession *s, gboolean gained_authorization, gpointer user_data);
    static void request(PolkitAgentSession *s, gchar *request, gboolean echo_on, gpointer user_data);
    static void showError(PolkitAgentSession *s, gchar *text, gpointer user_data);
    static void showInfo(PolkitAgentSession *s, gchar *text, gpointer user_data);

    AsyncResult *result;
    PolkitAgentSession *polkitAgentSession;
};

void Session::Private::completed(PolkitAgentSession *s, gboolean gained_authorization,
        gpointer user_data)
{
  Session *session = (Session *)user_data;
  emit(session)->completed(gained_authorization);

  //free session here as polkit documentation asks
  if (session->d->polkitAgentSession)
  {
    g_object_unref(session->d->polkitAgentSession);
  }
  session->d->polkitAgentSession = nullptr;
}

void Session::Private::request(PolkitAgentSession *s, gchar *request, gboolean echo_on,
        gpointer user_data)
{
  emit((Session*)user_data)->request(TQString::fromUtf8(request), echo_on);
}

void Session::Private::showError(PolkitAgentSession *s, gchar *text, gpointer user_data)
{
  emit((Session*)user_data)->showError(TQString::fromUtf8(text));
}

void Session::Private::showInfo(PolkitAgentSession *s, gchar *text, gpointer user_data)
{
  emit((Session*)user_data)->showInfo(TQString::fromUtf8(text));
}

//--------------------------------------
// Session
//--------------------------------------

Session::Session(const Identity &identity, const TQString &cookie, AsyncResult *result,
        TQObject *parent) : TQObject(parent), d(new Private)
{
  d->result = result;
  d->polkitAgentSession = polkit_agent_session_new(identity.identity(), cookie.utf8().data());
  g_signal_connect(G_OBJECT(d->polkitAgentSession), "completed", G_CALLBACK(Private::completed), this);
  g_signal_connect(G_OBJECT(d->polkitAgentSession), "request", G_CALLBACK(Private::request), this);
  g_signal_connect(G_OBJECT(d->polkitAgentSession), "show-error", G_CALLBACK(Private::showError), this);
  g_signal_connect(G_OBJECT(d->polkitAgentSession), "show-info", G_CALLBACK(Private::showInfo), this);
}

Session::Session(PolkitAgentSession *pkAgentSession, TQObject *parent)
        : TQObject(parent), d(new Private)
{
  d->polkitAgentSession = pkAgentSession;
  g_signal_connect(G_OBJECT(d->polkitAgentSession), "completed", G_CALLBACK(Private::completed), this);
  g_signal_connect(G_OBJECT(d->polkitAgentSession), "request", G_CALLBACK(Private::request), this);
  g_signal_connect(G_OBJECT(d->polkitAgentSession), "show-error", G_CALLBACK(Private::showError), this);
  g_signal_connect(G_OBJECT(d->polkitAgentSession), "show-info", G_CALLBACK(Private::showInfo), this);
}

Session::~Session()
{
  if (d->polkitAgentSession)
  {
    g_object_unref(d->polkitAgentSession);
  }

  delete d;
}

void Session::initiate()
{
  polkit_agent_session_initiate(d->polkitAgentSession);
}

void Session::setResponse(const TQString &response)
{
  polkit_agent_session_response(d->polkitAgentSession, response.utf8().data());
}

void Session::cancel()
{
  polkit_agent_session_cancel(d->polkitAgentSession);
}

//--------------------------------------
// AsyncResult::Private
//--------------------------------------

class AsyncResult::Private
{
  public:
    Private(GSimpleAsyncResult *r) : result(r)
    {
    }

    GSimpleAsyncResult *result;
};

AsyncResult* Session::result()
{
  return d->result;
}

AsyncResult::AsyncResult(GSimpleAsyncResult *result) : d(new Private(result))
{
}

AsyncResult::~AsyncResult()
{
  if (d->result)
  {
    g_object_unref(d->result);
  }
}

void AsyncResult::setCompleted()
{
  if (d->result == nullptr)
  {
    return;
  }
  g_simple_async_result_complete(d->result);
  // Assure that completed won't be called twice
  if (d->result)
  {
    g_object_unref(d->result);
  }
  d->result = nullptr;
}

void AsyncResult::setError(const TQString &text)
{
  if (d->result == nullptr)
  {
    return;
  }
  g_simple_async_result_set_error(d->result, POLKIT_ERROR, POLKIT_ERROR_FAILED, "%s",
          text.utf8().data());
}

#include "polkit-tqt-agent-session.moc"
