/*
 * Copyright (C) 2022 Purism SPC
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * Author: Guido Günther <agx@sigxcpu.org>
 */


#define G_LOG_DOMAIN "ms-window"

#include "mobile-settings-config.h"

#include "ms-application.h"
#include "ms-window.h"

#include "ms-plugin-panel.h"

#include "conf-tweaks/ms-tweaks-parser.h"
#include "conf-tweaks/ms-tweaks-preferences-page.h"

#include <glib/gi18n.h>


struct _MsWindow {
  AdwApplicationWindow     parent_instance;

  GtkSearchBar            *search_bar;
  GtkSearchEntry          *search_entry;

  AdwNavigationSplitView  *split_view;
  GtkStack                *stack;
  MsPanelSwitcher         *panel_switcher;

  GSettings               *settings;
  MsTweaksParser          *ms_tweaks_parser;
};

G_DEFINE_TYPE (MsWindow, ms_window, ADW_TYPE_APPLICATION_WINDOW)


static void
on_search_entry_changed (GtkSearchEntry *search_entry,
                         MsWindow       *self)
{
  ms_panel_switcher_set_search_query (self->panel_switcher,
                                      gtk_editable_get_text (GTK_EDITABLE (search_entry)));
}


static void
on_search_entry_activated (GtkSearchEntry *search_entry,
                           MsWindow       *self)
{
  ms_panel_switcher_set_active_panel_index (self->panel_switcher, 0);
}


static void
show_content_cb (MsWindow *self)
{
  const char *panelname;

  adw_navigation_split_view_set_show_content (self->split_view, TRUE);

  panelname = gtk_stack_get_visible_child_name (self->stack);

  g_settings_set_string (self->settings, "last-panel", panelname);

  /* Clear search entry to display all panels again */
  if (gtk_search_bar_get_search_mode (self->search_bar)) {
    gtk_search_bar_set_search_mode (self->search_bar, FALSE);
    gtk_editable_delete_text (GTK_EDITABLE (self->search_entry), 0, -1);
  }
}


static char *
stack_child_to_tile (gpointer target, GtkStack *stack, GtkWidget *child)
{
  const char *title;
  GtkStackPage *page;

  g_assert (GTK_IS_STACK (stack));
  g_assert (GTK_IS_WIDGET (child));

  page = gtk_stack_get_page (stack, child);
  title = gtk_stack_page_get_title (page);
  if (title == NULL)
    title = gtk_stack_page_get_name (page);

  return g_strdup (title);
}


static void
add_ms_tweaks_page (gpointer value, gpointer user_data)
{
  MsWindow *self = MS_WINDOW (user_data);
  MsTweaksPage *page_data = (MsTweaksPage *) value;
  MsTweaksPreferencesPage *page_widget = ms_tweaks_preferences_page_new (page_data);

  if (page_widget) {
    GtkStackPage *stack_page = gtk_stack_add_titled (self->stack,
                                                     GTK_WIDGET (page_widget), page_data->name_i18n,
                                                     page_data->name_i18n);
    /* TODO: Read icon from base64 property of settings definitions. */
    gtk_stack_page_set_icon_name (stack_page, "conf-tweaks-symbolic");
  }
}


static void
do_toggle_conf_tweaks (GSettings *settings, char *key, gpointer user_data)
{
  MsWindow *self = MS_WINDOW (user_data);
  gboolean conf_tweaks_enabled = g_settings_get_boolean (settings, key);

  /* Flip! */
  conf_tweaks_enabled = !conf_tweaks_enabled;

  ms_panel_switcher_refilter (self->panel_switcher,
                              conf_tweaks_enabled ? GTK_FILTER_CHANGE_LESS_STRICT : GTK_FILTER_CHANGE_MORE_STRICT);
}


static void
ms_settings_window_constructed (GObject *object)
{
  MsWindow *self = MS_WINDOW (object);
  MsApplication *app = MS_APPLICATION (g_application_get_default ());
  GtkWidget *device_panel;
  GHashTable *parser_page_table = NULL;

  G_OBJECT_CLASS (ms_window_parent_class)->constructed (object);

  if (gtk_stack_get_child_by_name (self->stack, "device") == NULL) {
    const char *title;

    g_assert (GTK_IS_APPLICATION (app));
    device_panel = ms_application_get_device_panel (app);
    if (device_panel) {
      GtkStackPage *page;

      title = ms_plugin_panel_get_title (MS_PLUGIN_PANEL (device_panel));
      page = gtk_stack_add_titled (self->stack, device_panel, "device", title ?: _("Device"));
      gtk_stack_page_set_icon_name (page, "phone-symbolic");
    }
  }

  ms_tweaks_parser_parse_definition_files (self->ms_tweaks_parser, TWEAKS_DATA_DIR);
  parser_page_table = ms_tweaks_parser_get_page_table (self->ms_tweaks_parser);

  if (g_hash_table_size (parser_page_table) != 0) {
    g_autoptr (GList) pages_sorted_by_weight = ms_tweaks_parser_sort_by_weight (parser_page_table);
    g_autoptr (GAction) toggle_conf_tweaks;

    g_list_foreach (pages_sorted_by_weight, add_ms_tweaks_page, self);

    toggle_conf_tweaks = g_settings_create_action (self->settings, "enable-conf-tweaks");
    g_signal_connect (self->settings, "changed::enable-conf-tweaks", G_CALLBACK (do_toggle_conf_tweaks), self);
    g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (toggle_conf_tweaks));
  }
}


static void
ms_settings_window_dispose (GObject *object)
{
  MsWindow *self = MS_WINDOW (object);

  g_clear_object (&self->settings);
  g_clear_object (&self->ms_tweaks_parser);

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


static void
ms_window_class_init (MsWindowClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);

  object_class->constructed = ms_settings_window_constructed;
  object_class->dispose = ms_settings_window_dispose;

  gtk_widget_class_set_template_from_resource (widget_class,
                                               "/mobi/phosh/MobileSettings/ui/ms-window.ui");
  gtk_widget_class_bind_template_child (widget_class, MsWindow, search_bar);
  gtk_widget_class_bind_template_child (widget_class, MsWindow, search_entry);
  gtk_widget_class_bind_template_child (widget_class, MsWindow, split_view);
  gtk_widget_class_bind_template_child (widget_class, MsWindow, stack);
  gtk_widget_class_bind_template_child (widget_class, MsWindow, panel_switcher);

  gtk_widget_class_bind_template_callback (widget_class, on_search_entry_changed);
  gtk_widget_class_bind_template_callback (widget_class, on_search_entry_activated);
  gtk_widget_class_bind_template_callback (widget_class, show_content_cb);
  gtk_widget_class_bind_template_callback (widget_class, stack_child_to_tile);
}

static void
ms_window_init (MsWindow *self)
{
  self->settings = g_settings_new ("mobi.phosh.MobileSettings");
  self->ms_tweaks_parser = ms_tweaks_parser_new ();

  gtk_widget_init_template (GTK_WIDGET (self));
  show_content_cb (self);

  gtk_search_bar_set_key_capture_widget (self->search_bar, GTK_WIDGET (self));
}


GtkSelectionModel *
ms_window_get_stack_pages (MsWindow *self)
{
  g_assert (MS_IS_WINDOW (self));

  return gtk_stack_get_pages (self->stack);
}


MsPanelSwitcher *
ms_window_get_panel_switcher (MsWindow *self)
{
  g_assert (MS_IS_WINDOW (self));

  return self->panel_switcher;
}
