// ------------------------------ VSNAMEL.C --------------------
// Bye Jare of Iguana (Javier Ar‚valo Baeza) in 1995.
// Copyright (C) 1994-1995 by the author.

#include "vsnamel.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

extern  bool VSNL_Init(VSNL_PNameTree t) {
    assert(t != NULL);
    *t = NULL;
    return TRUE;
}

extern  void VSNL_End(VSNL_PNameTree t) {
    assert(t != NULL);
    if (*t == NULL)
        return;
    if ((*t)->left != NULL)
        VSNL_End(&(*t)->left);
    if ((*t)->right != NULL)
        VSNL_End(&(*t)->right);
    DISPOSE(*t);
}

extern  VSNL_PName VSNL_AddName(VSNL_PNameTree t, const char *name) {
    VSNL_PName p, *g;

    assert(t != NULL);
    assert(name != NULL);
    g = t;
    while (*g != NULL) {
        int rez;

        p = *g;
        rez = strnicmp(p->name, name, sizeof(p->name));
        if (rez > 0)
            g = &p->left;
        else if (rez < 0)
            g = &p->right;
        else                    // found!
            return p;
    }
        // Not found, let's add a node.

    p = NEW(sizeof(*p));
    if (p == NULL)
        return NULL;

    *g = p;
    p->left  = NULL;
    p->right = NULL;
    strncpy(p->name, name, sizeof(p->name));
    p->data = NULL;
    return p;
}

extern  void     VSNL_AddTree(VSNL_PNameTree t, VSNL_TNameTree src) {
    VSNL_PName p, *g;

    assert(t != NULL);
    if (src == NULL)
        return;
    g = t;
    while (*g != NULL) {
        int rez;

        p = *g;
        rez = strnicmp(p->name, src->name, sizeof(p->name));
        if (rez > 0)
            g = &p->left;
        else if (rez < 0)
            g = &p->right;
        else                    // found!
            BASE_Abort("AddTree found the name already in the tree.\n");
    }
        // Not found, let's add a node.

    *g = src;
}


extern  VSNL_PName VSNL_FindName(VSNL_PNameTree t, const char *name) {
    VSNL_PName p;

    assert(t != NULL);
    assert(name != NULL);
    p = *t;
    while (p != NULL) {
        int rez;

        rez = strnicmp(p->name, name, sizeof(p->name));
        if (rez > 0)
            p = p->left;
        else if (rez < 0)
            p = p->right;
        else                    // found!
            return p;
    }
    return NULL;
}

static bool printnodes(VSNL_PName *n, void *data) {
    printf(" Node has name %s\n", (*n)->name);
    return TRUE;
}

extern  void VSNL_DelName(VSNL_PNameTree t, const char *name) {
    VSNL_PName p, q, *g;

    assert(t != NULL);
    assert(name != NULL);
    g = t;
    while (*g != NULL) {
        int rez;

        p = *g;
        rez = strnicmp(p->name, name, sizeof(p->name));
        if (rez > 0)
            g = &p->left;
        else if (rez < 0)
            g = &p->right;
        else {                   // found!
            q = p->right;       // Save leaves.
            p = p->left;
            DISPOSE(*g);        // Delete node.
                // Now the leaves are separated from the root.
                // Fit them in again.
            VSNL_AddTree(g, p);
            VSNL_AddTree(g, q);
            return;
        }
    }
        // Not found!

    printf("Printing tree...\n");
    VSNL_WalkTree(t, printnodes, NULL);

    BASE_Abort("Node not found for deletion searching \"%s\"!", name);
}

extern  bool VSNL_WalkTree(VSNL_PNameTree t, VSNL_PWalkFunction func, void *data) {
    assert(t != NULL);
    assert(func != NULL);
    if (*t != NULL) {
        if (!VSNL_WalkTree(&(*t)->left, func, data))  // First the children.
            return FALSE;
        if (!VSNL_WalkTree(&(*t)->right, func, data))
            return FALSE;
        if (!func(t, data))
            return FALSE;
    }
    return TRUE;
}

// ------------------------------ VSNAMEL.C --------------------
