/*
 * Copyright (C) 2012 Igalia S.L.
 *
 * 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.
 */

#include "config.h"
#include "WebKitAuthenticationDialog.h"

#include "AuthenticationDecisionListener.h"
#include "WebKitAuthenticationRequestPrivate.h"
#include "WebKitCredentialPrivate.h"
#include "WebKitWebView.h"
#include <glib/gi18n-lib.h>
#include <wtf/glib/GRefPtr.h>
#include <wtf/glib/GUniquePtr.h>
#include <wtf/glib/WTFGType.h>
#include <wtf/text/CString.h>

using namespace WebKit;

struct _WebKitAuthenticationDialogPrivate {
    GRefPtr<WebKitAuthenticationRequest> request;
    CredentialStorageMode credentialStorageMode;
    GtkWidget* loginEntry;
    GtkWidget* passwordEntry;
    GtkWidget* rememberCheckButton;
    GtkWidget* defaultButton;
    unsigned long authenticationCancelledID;
};

WEBKIT_DEFINE_TYPE(WebKitAuthenticationDialog, webkit_authentication_dialog, WEBKIT_TYPE_WEB_VIEW_DIALOG)

static void okButtonClicked(GtkButton*, WebKitAuthenticationDialog* authDialog)
{
    WebKitAuthenticationDialogPrivate* priv = authDialog->priv;
    const char* username = gtk_entry_get_text(GTK_ENTRY(priv->loginEntry));
    const char* password = gtk_entry_get_text(GTK_ENTRY(priv->passwordEntry));
    bool rememberPassword = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->rememberCheckButton));

    WebCore::CredentialPersistence persistence = rememberPassword && priv->credentialStorageMode == AllowPersistentStorage ?
        WebCore::CredentialPersistencePermanent : WebCore::CredentialPersistenceForSession;

    // FIXME: Use a stack allocated WebKitCredential.
    WebKitCredential* credential = webkitCredentialCreate(WebCore::Credential(String::fromUTF8(username), String::fromUTF8(password), persistence));
    webkit_authentication_request_authenticate(priv->request.get(), credential);
    webkit_credential_free(credential);
    gtk_widget_destroy(GTK_WIDGET(authDialog));
}

static void cancelButtonClicked(GtkButton*, WebKitAuthenticationDialog* authDialog)
{
    webkit_authentication_request_authenticate(authDialog->priv->request.get(), nullptr);
    gtk_widget_destroy(GTK_WIDGET(authDialog));
}

static void authenticationCancelled(WebKitAuthenticationRequest*, WebKitAuthenticationDialog* authDialog)
{
    gtk_widget_destroy(GTK_WIDGET(authDialog));
}

static GtkWidget* createLabelWithLineWrap(const char* text)
{
    GtkWidget* label = gtk_label_new(text);
    gtk_widget_set_halign(label, GTK_ALIGN_START);
    gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
    gtk_label_set_max_width_chars(GTK_LABEL(label), 40);
    return label;
}

static void webkitAuthenticationDialogInitialize(WebKitAuthenticationDialog* authDialog)
{
    GtkWidget* vBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20);

    GtkWidget* box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_style_context_add_class(gtk_widget_get_style_context(box), GTK_STYLE_CLASS_TITLEBAR);
    gtk_widget_set_size_request(box, -1, 16);
    GtkWidget* title = gtk_label_new(_("Authentication Required"));
    gtk_widget_set_margin_top(title, 6);
    gtk_widget_set_margin_bottom(title, 6);
    gtk_style_context_add_class(gtk_widget_get_style_context(title), GTK_STYLE_CLASS_TITLE);
    gtk_box_set_center_widget(GTK_BOX(box), title);
    gtk_widget_show(title);
    gtk_box_pack_start(GTK_BOX(vBox), box, TRUE, FALSE, 0);
    gtk_widget_show(box);

    GtkWidget* buttonBox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_EXPAND);
    gtk_widget_set_hexpand(buttonBox, TRUE);
    gtk_style_context_add_class(gtk_widget_get_style_context(buttonBox), "dialog-action-area");

    GtkWidget* button = gtk_button_new_with_mnemonic(_("_Cancel"));
    g_signal_connect(button, "clicked", G_CALLBACK(cancelButtonClicked), authDialog);
    gtk_box_pack_start(GTK_BOX(buttonBox), button, FALSE, TRUE, 0);
    gtk_widget_show(button);

    WebKitAuthenticationDialogPrivate* priv = authDialog->priv;
    button = gtk_button_new_with_mnemonic(_("_Authenticate"));
    priv->defaultButton = button;
    g_signal_connect(button, "clicked", G_CALLBACK(okButtonClicked), authDialog);
    gtk_widget_set_can_default(button, TRUE);
    gtk_box_pack_end(GTK_BOX(buttonBox), button, FALSE, TRUE, 0);
    gtk_widget_show(button);

    GtkWidget* authBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
    gtk_widget_set_margin_start(authBox, 10);
    gtk_widget_set_margin_end(authBox, 10);

    const WebCore::AuthenticationChallenge& challenge = webkitAuthenticationRequestGetAuthenticationChallenge(priv->request.get())->core();
    // Prompt on the HTTP authentication dialog.
    GUniquePtr<char> prompt(g_strdup_printf(_("Authentication required by %s:%i"),
        challenge.protectionSpace().host().utf8().data(), challenge.protectionSpace().port()));
    GtkWidget* label = createLabelWithLineWrap(prompt.get());
    gtk_widget_show(label);
    gtk_box_pack_start(GTK_BOX(authBox), label, FALSE, FALSE, 0);

    String realm = challenge.protectionSpace().realm();
    if (!realm.isEmpty()) {
        // Label on the HTTP authentication dialog. %s is a (probably English) message from the website.
        GUniquePtr<char> message(g_strdup_printf(_("The site says: “%s”"), realm.utf8().data()));
        label = createLabelWithLineWrap(message.get());
        gtk_widget_show(label);
        gtk_box_pack_start(GTK_BOX(authBox), label, FALSE, FALSE, 0);
    }

    // Check button on the HTTP authentication dialog.
    priv->rememberCheckButton = gtk_check_button_new_with_mnemonic(_("_Remember password"));
    gtk_label_set_line_wrap(GTK_LABEL(gtk_bin_get_child(GTK_BIN(priv->rememberCheckButton))), TRUE);

    priv->loginEntry = gtk_entry_new();
    gtk_widget_set_hexpand(priv->loginEntry, TRUE);
    gtk_entry_set_activates_default(GTK_ENTRY(priv->loginEntry), TRUE);
    gtk_widget_show(priv->loginEntry);

    // Entry on the HTTP authentication dialog.
    GtkWidget* loginLabel = gtk_label_new_with_mnemonic(_("_Username"));
    gtk_label_set_mnemonic_widget(GTK_LABEL(loginLabel), priv->loginEntry);
    gtk_widget_set_halign(loginLabel, GTK_ALIGN_END);
    gtk_style_context_add_class(gtk_widget_get_style_context(loginLabel), GTK_STYLE_CLASS_DIM_LABEL);
    gtk_widget_show(loginLabel);

    priv->passwordEntry = gtk_entry_new();
    gtk_widget_set_hexpand(priv->passwordEntry, TRUE);
    gtk_entry_set_activates_default(GTK_ENTRY(priv->passwordEntry), TRUE);
    gtk_widget_show(priv->passwordEntry);

    // Entry on the HTTP authentication dialog.
    GtkWidget* passwordLabel = gtk_label_new_with_mnemonic(_("_Password"));
    gtk_label_set_mnemonic_widget(GTK_LABEL(passwordLabel), priv->passwordEntry);
    gtk_widget_set_halign(passwordLabel, GTK_ALIGN_END);
    gtk_style_context_add_class(gtk_widget_get_style_context(passwordLabel), GTK_STYLE_CLASS_DIM_LABEL);
    gtk_widget_show(passwordLabel);

    GtkWidget* grid = gtk_grid_new();
    gtk_grid_set_column_spacing(GTK_GRID(grid), 6);
    gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
    gtk_grid_attach(GTK_GRID(grid), loginLabel, 0, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), priv->loginEntry, 1, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), passwordLabel, 0, 1, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), priv->passwordEntry, 1, 1, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), priv->rememberCheckButton, 1, 2, 1, 1);
    gtk_widget_show(grid);
    gtk_box_pack_start(GTK_BOX(authBox), grid, FALSE, FALSE, 0);

    gtk_entry_set_visibility(GTK_ENTRY(priv->passwordEntry), FALSE);
    gtk_widget_set_visible(priv->rememberCheckButton, priv->credentialStorageMode != DisallowPersistentStorage && !realm.isEmpty());

    const WebCore::Credential& credentialFromPersistentStorage = challenge.proposedCredential();
    if (!credentialFromPersistentStorage.isEmpty()) {
        gtk_entry_set_text(GTK_ENTRY(priv->loginEntry), credentialFromPersistentStorage.user().utf8().data());
        gtk_entry_set_text(GTK_ENTRY(priv->passwordEntry), credentialFromPersistentStorage.password().utf8().data());
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->rememberCheckButton), TRUE);
    }

    gtk_box_pack_start(GTK_BOX(vBox), authBox, TRUE, TRUE, 0);
    gtk_widget_show(authBox);

    gtk_box_pack_end(GTK_BOX(vBox), buttonBox, FALSE, TRUE, 0);
    gtk_widget_show(buttonBox);

    gtk_container_add(GTK_CONTAINER(authDialog), vBox);
    gtk_widget_show(vBox);

    authDialog->priv->authenticationCancelledID = g_signal_connect(authDialog->priv->request.get(), "cancelled", G_CALLBACK(authenticationCancelled), authDialog);
}

static void webkitAuthenticationDialogMap(GtkWidget* widget)
{
    WebKitAuthenticationDialogPrivate* priv = WEBKIT_AUTHENTICATION_DIALOG(widget)->priv;
    gtk_widget_grab_focus(priv->loginEntry);
    gtk_widget_grab_default(priv->defaultButton);

    GTK_WIDGET_CLASS(webkit_authentication_dialog_parent_class)->map(widget);
}

static void webkitAuthenticationDialogDispose(GObject* object)
{
    WebKitAuthenticationDialogPrivate* priv = WEBKIT_AUTHENTICATION_DIALOG(object)->priv;
    if (priv->authenticationCancelledID) {
        g_signal_handler_disconnect(priv->request.get(), priv->authenticationCancelledID);
        priv->authenticationCancelledID = 0;
    }

    G_OBJECT_CLASS(webkit_authentication_dialog_parent_class)->dispose(object);
}

static void webkit_authentication_dialog_class_init(WebKitAuthenticationDialogClass* klass)
{
    GObjectClass* objectClass = G_OBJECT_CLASS(klass);
    objectClass->dispose = webkitAuthenticationDialogDispose;

    GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(klass);
    widgetClass->map = webkitAuthenticationDialogMap;
}

GtkWidget* webkitAuthenticationDialogNew(WebKitAuthenticationRequest* request, CredentialStorageMode mode)
{
    WebKitAuthenticationDialog* authDialog = WEBKIT_AUTHENTICATION_DIALOG(g_object_new(WEBKIT_TYPE_AUTHENTICATION_DIALOG, NULL));
    authDialog->priv->request = request;
    authDialog->priv->credentialStorageMode = mode;
    webkitAuthenticationDialogInitialize(authDialog);
    return GTK_WIDGET(authDialog);
}
