/*
 * Copyright (C) 2017 Canonical Ltd.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2 or version 3 of the License.
 * See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
 */

#include "snapd-alias.h"
#include "snapd-enum-types.h"

/**
 * SECTION: snapd-alias
 * @short_description: App aliases.
 * @include: snapd-glib/snapd-glib.h
 *
 * A #SnapdAlias represents an optional alias that can be used for an app.
 * Aliases can be queried using snapd_client_get_aliases_sync() and are used in
 * snapd_client_enable_aliases_sync(), snapd_client_disable_aliases_sync() and
 * snapd_client_reset_aliases_sync().
 */

/**
 * SnapdAlias:
 *
 * #SnapdAlias contains alias information for a Snap.
 *
 * Aliases are used to provide alternative binary names for Snap apps.
 *
 * Since: 1.8
 */

struct _SnapdAlias {
  GObject parent_instance;

  gchar *command;
  gchar *name;
  gchar *snap;
  gchar *app_auto;
  gchar *app_manual;
  SnapdAliasStatus status;
};

enum {
  PROP_NAME = 1,
  PROP_SNAP,
  PROP_STATUS,
  PROP_COMMAND,
  PROP_APP_AUTO,
  PROP_APP_MANUAL,
  PROP_LAST
};

G_DEFINE_TYPE(SnapdAlias, snapd_alias, G_TYPE_OBJECT)

/**
 * snapd_alias_get_app:
 * @alias: a #SnapdAlias.
 *
 * Get the app this is an alias for.
 *
 * Returns: (allow-none): an app name or %NULL.
 *
 * Since: 1.8
 * Deprecated: 1.25: Use snapd_alias_get_app_manual() or
 * snapd_alias_get_app_auto().
 */
const gchar *snapd_alias_get_app(SnapdAlias *self) {
  g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL);
  return NULL;
}

/**
 * snapd_alias_get_app_auto:
 * @alias: a #SnapdAlias.
 *
 * Get the app this alias has been automatically set to (status is
 * %SNAPD_ALIAS_STATUS_AUTO). Can be overridden when status is
 * %SNAPD_ALIAS_STATUS_MANUAL.
 *
 * Returns: (allow-none): an app name or %NULL.
 *
 * Since: 1.25
 */
const gchar *snapd_alias_get_app_auto(SnapdAlias *self) {
  g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL);
  return self->app_auto;
}

/**
 * snapd_alias_get_app_manual:
 * @alias: a #SnapdAlias.
 *
 * Get the app this alias has been manually set to (status is
 * %SNAPD_ALIAS_STATUS_MANUAL). This overrides the app from
 * snapd_alias_get_app_auto().
 *
 * Returns: (allow-none): an app name or %NULL.
 *
 * Since: 1.25
 */
const gchar *snapd_alias_get_app_manual(SnapdAlias *self) {
  g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL);
  return self->app_manual;
}

/**
 * snapd_alias_get_command:
 * @alias: a #SnapdAlias.
 *
 * Get the command this alias runs.
 *
 * Returns: a command.
 *
 * Since: 1.25
 */
const gchar *snapd_alias_get_command(SnapdAlias *self) {
  g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL);
  return self->command;
}

/**
 * snapd_alias_get_name:
 * @alias: a #SnapdAlias.
 *
 * Get the name of this alias.
 *
 * Returns: an alias name.
 *
 * Since: 1.8
 */
const gchar *snapd_alias_get_name(SnapdAlias *self) {
  g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL);
  return self->name;
}

/**
 * snapd_alias_get_snap:
 * @alias: a #SnapdAlias.
 *
 * Get the snap this alias is for.
 *
 * Returns: a snap name.
 *
 * Since: 1.8
 */
const gchar *snapd_alias_get_snap(SnapdAlias *self) {
  g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL);
  return self->snap;
}

/**
 * snapd_alias_get_status:
 * @alias: a #SnapdAlias.
 *
 * Get the status of this alias.
 *
 * Return: a #SnapdAliasStatus.
 *
 * Since: 1.8
 */
SnapdAliasStatus snapd_alias_get_status(SnapdAlias *self) {
  g_return_val_if_fail(SNAPD_IS_ALIAS(self), SNAPD_ALIAS_STATUS_UNKNOWN);
  return self->status;
}

static void snapd_alias_set_property(GObject *object, guint prop_id,
                                     const GValue *value, GParamSpec *pspec) {
  SnapdAlias *self = SNAPD_ALIAS(object);

  switch (prop_id) {
  case PROP_APP_AUTO:
    g_free(self->app_auto);
    self->app_auto = g_strdup(g_value_get_string(value));
    break;
  case PROP_APP_MANUAL:
    g_free(self->app_manual);
    self->app_manual = g_strdup(g_value_get_string(value));
    break;
  case PROP_COMMAND:
    g_free(self->command);
    self->command = g_strdup(g_value_get_string(value));
    break;
  case PROP_NAME:
    g_free(self->name);
    self->name = g_strdup(g_value_get_string(value));
    break;
  case PROP_SNAP:
    g_free(self->snap);
    self->snap = g_strdup(g_value_get_string(value));
    break;
  case PROP_STATUS:
    self->status = g_value_get_enum(value);
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    break;
  }
}

static void snapd_alias_get_property(GObject *object, guint prop_id,
                                     GValue *value, GParamSpec *pspec) {
  SnapdAlias *self = SNAPD_ALIAS(object);

  switch (prop_id) {
  case PROP_APP_AUTO:
    g_value_set_string(value, self->app_auto);
    break;
  case PROP_APP_MANUAL:
    g_value_set_string(value, self->app_manual);
    break;
  case PROP_COMMAND:
    g_value_set_string(value, self->command);
    break;
  case PROP_NAME:
    g_value_set_string(value, self->name);
    break;
  case PROP_SNAP:
    g_value_set_string(value, self->snap);
    break;
  case PROP_STATUS:
    g_value_set_enum(value, self->status);
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    break;
  }
}

static void snapd_alias_finalize(GObject *object) {
  SnapdAlias *self = SNAPD_ALIAS(object);

  g_clear_pointer(&self->app_auto, g_free);
  g_clear_pointer(&self->app_manual, g_free);
  g_clear_pointer(&self->command, g_free);
  g_clear_pointer(&self->name, g_free);
  g_clear_pointer(&self->snap, g_free);

  G_OBJECT_CLASS(snapd_alias_parent_class)->finalize(object);
}

static void snapd_alias_class_init(SnapdAliasClass *klass) {
  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);

  gobject_class->set_property = snapd_alias_set_property;
  gobject_class->get_property = snapd_alias_get_property;
  gobject_class->finalize = snapd_alias_finalize;

  g_object_class_install_property(
      gobject_class, PROP_APP_AUTO,
      g_param_spec_string(
          "app-auto", "app-auto",
          "App this alias is for (when status is SNAPD_ALIAS_STATUS_AUTO)",
          NULL,
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
              G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

  g_object_class_install_property(
      gobject_class, PROP_APP_MANUAL,
      g_param_spec_string(
          "app-manual", "app-manual",
          "App this alias is for (when status is SNAPD_ALIAS_STATUS_MANUAL)",
          NULL,
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
              G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

  g_object_class_install_property(
      gobject_class, PROP_COMMAND,
      g_param_spec_string("command", "command", "Command this alias runs", NULL,
                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
                              G_PARAM_STATIC_BLURB));

  g_object_class_install_property(
      gobject_class, PROP_NAME,
      g_param_spec_string("name", "name", "Name of alias", NULL,
                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
                              G_PARAM_STATIC_BLURB));

  g_object_class_install_property(
      gobject_class, PROP_SNAP,
      g_param_spec_string("snap", "snap", "Snap this alias is for", NULL,
                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
                              G_PARAM_STATIC_BLURB));

  g_object_class_install_property(
      gobject_class, PROP_STATUS,
      g_param_spec_enum("status", "status", "Alias status",
                        SNAPD_TYPE_ALIAS_STATUS, SNAPD_ALIAS_STATUS_UNKNOWN,
                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                            G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
                            G_PARAM_STATIC_BLURB));
}

static void snapd_alias_init(SnapdAlias *self) {}
