
#include "zori.h"
#include "zori_registry.h"

/* registry functionality */

/** Compare registry entries. */
int zori_registry_entry_compare(const void * v1, const void * v2) {
  const struct zori_registry_entry * entry1 = v1;
  const struct zori_registry_entry * entry2 = v2;
  return (entry2->id - entry1->id);
}

/** Initialize the registry. */
zori_id zori_registry_init(struct zori_registry * registry) {
  miao_init(registry);
  return ZORI_ID_OK;
}

/** Destroy the registry */
void zori_registry_destroy(struct zori_registry * registry) {
  if(registry) { 
    miao_done(registry);
  }
}


/** Add an entry to the registry. */
zori_id 
zori_registry_add(struct zori_registry * registry, zori_id id, 
struct zori_widget * widget) {
  struct zori_registry_entry entry = { id, widget };
  if (miao_push(registry, entry)) { 
    miao_qsort(registry, zori_registry_entry_compare);
    return ZORI_ID_OK;
  }
  return ZORI_ID_ENOMEM;
}

/** Look up an entry in the registry. */
struct zori_registry_entry *  
zori_registry_lookup_entry(struct zori_registry * registry, zori_id id) {
  struct zori_registry_entry key = { id, NULL };
  return miao_bsearch(registry, zori_registry_entry_compare, &key);
}


/** Look up a widget in the registry. */
struct zori_widget *  
zori_registry_lookup(struct zori_registry * registry, zori_id id) {
  struct zori_widget * result = NULL;
  struct zori_registry_entry * entry = NULL;
  
  entry = zori_registry_lookup_entry(registry, id);
  if (entry) { 
    result = entry->widget;
  }
  return result;
}



/** Remove an entry from the registry. */
zori_id 
zori_registry_remove(struct zori_registry * registry, zori_id id) {
  struct zori_registry_entry * entry = NULL;
  entry = zori_registry_lookup_entry(registry, id);
  if (entry) {
    miao_delete_entry(registry, entry);
  }
  return ZORI_ID_OK;
}

/** The global registry for Zori. */
static struct zori_registry * the_zori_registry = NULL;

/** Intializes the global registry for zori. */
zori_id zori_initialize_registry() {
  the_zori_registry = calloc(1, sizeof(*the_zori_registry));
  if (!the_zori_registry) return ZORI_ID_ENOMEM;
  return zori_registry_init(the_zori_registry);
}

/** Destroys the global registry for zori. */
zori_id zori_destroy_registry() {
  zori_registry_destroy(the_zori_registry); 
  free(the_zori_registry);
  the_zori_registry = NULL;
  return ZORI_ID_OK;
}


/** Returns the global registry for Zori. */
struct zori_registry * zori_get_registry() {
  return the_zori_registry;
}








