/*===================================================================

        Copyright (c) 2006  Unigraphics Solutions Corporation
                     Unpublished - All rights reserved

===================================================================*/

/******************************************************************************
 *                                                                            *
 * DESCRIPTION -                                                              *
 *   This program shows how to use the following NX Open API routine(s):      *
 *                                                                            *
 *         UF_ASSEM_ask_arrangements_in_part                                  *
 *         UF_ASSEM_ask_active_arrangement                                    *
 *         UF_ASSEM_set_active_arrangement                                    *
 *         UF_ASSEM_ask_used_arrangement                                      *
 *         UF_ASSEM_set_used_arrangement                                      *
 *         UF_ASSEM_ask_default_arrangement                                   *
 *         UF_ASSEM_set_default_arrangement                                   *
 *         UF_ASSEM_ask_name_of_arrangement                                   *
 *                                                                            *
 * PROGRAM DESCRIPTION -                                                      *
 *   This example requires a displayed part with components where both the    *
 *   displayed part and the components all contain multiple design            *
 *   arrangements.  The example changes the active and default                *
 *   arrangement of the displayed part, then changes the used arrangement     *
 *   of each component in turn.  As each arrangement is changed, a message    *
 *   is written to standard output to indicate what the arrangement has       *
 *   been changed from and to.
 *                                                                            *
 *                                                                            *
 ******************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <uf_defs.h>
#include <uf.h>
#include <uf_part.h>
#include <uf_assem.h>
#include <uf_cfi.h>

static int change_active_arrangement( tag_t part );
static int change_default_arrangement( tag_t part );
static int change_used_arrangement_of_components( tag_t component );
static int change_used_arrangement( tag_t component );

/*ARGSUSED*/
extern void ufusr(char *name, int *rtcode, int rtlen)
{
    tag_t root_part_occ = NULL_TAG;
    tag_t displayed_part = NULL_TAG;

    UF_initialize();

    strcpy(name, "");
    displayed_part = UF_PART_ask_display_part();
    if (displayed_part != NULL_TAG)
    {
        *rtcode  = change_active_arrangement( displayed_part );
        *rtcode |= change_default_arrangement( displayed_part );

        root_part_occ = UF_ASSEM_ask_root_part_occ(displayed_part);
        if (root_part_occ != NULL_TAG)
        {
            *rtcode |= change_used_arrangement_of_components(root_part_occ);
        }
    }

    if (*rtcode == 0)
    {
        /* This assumes we have successfully executed the program. */
        printf("The NX Open API program has succeeded\n Return code is %d",
               *rtcode);
    }

    else
    {
        /* This assumes we failed. */
        printf("The NX Open API program has failed\n Return code is %d",
               *rtcode);
    }


    UF_terminate();
}

static int change_active_arrangement( tag_t part )
{
    int     result = 0;
    int     n_arrangements;
    tag_t   init_active_arrangement;
    tag_t   *all_arrangements;
    char    *init_arrangement_name;

    result = UF_ASSEM_ask_active_arrangement( part, &init_active_arrangement );
    if (result != 0)
    {
        printf( "Unable to determine active arrangement\n" );
        return (result);
    }
    result = UF_ASSEM_ask_name_of_arrangement( init_active_arrangement, &init_arrangement_name );
    if (result != 0)
    {
        printf( "Unable to determine name of active arrangementuration\n" );
        return (result);
    }
    result = UF_ASSEM_ask_arrangements_in_part( part, &n_arrangements, &all_arrangements );
    if (result != 0)
    {
        printf( "Failed to retrieve list of all arrangements in part\n" );
        UF_free( init_arrangement_name );
        return (result);
    }

    if (n_arrangements > 1)
    {
        char    *new_arrangement_name;
        int     i;

        for (i = 0; i < n_arrangements; i++)
        {
            /*  Use the first non-active arrangements */
            if (all_arrangements[i] != init_active_arrangement)
                break;
        }

        result = UF_ASSEM_ask_name_of_arrangement( all_arrangements[i], &new_arrangement_name );
        if (result != 0)
        {
            printf( "Failed to extract name for new active arrangement\n" );
            UF_free( init_arrangement_name );
            UF_free( all_arrangements );
            return (result);
        }

        result = UF_ASSEM_set_active_arrangement( all_arrangements[i] );
        if (result != 0)
        {
            printf( "Failed to change active arrangement from %s to %s\n",
                    init_arrangement_name, new_arrangement_name );
            UF_free( init_arrangement_name );
            UF_free( all_arrangements );
            UF_free( new_arrangement_name );
            return (result);
        }

        printf( "The active arrangement has been changed from %s to %s\n",
                init_arrangement_name, new_arrangement_name );
        UF_free( new_arrangement_name );

    }
    else
    {
        printf( "Only 1 arrangement in the display part, could not change active arrangement from %s\n",
                init_arrangement_name );
    }

    UF_free( init_arrangement_name );
    UF_free( all_arrangements );
    return (result);
}

static int change_default_arrangement( tag_t part )
{
    int     result = 0;
    int     n_arrangements;
    tag_t   init_default_arrangement;
    tag_t   *all_arrangements;
    char    *init_arrangement_name;

    result = UF_ASSEM_ask_default_arrangement( part, &init_default_arrangement );
    if (result != 0)
    {
        printf( "Unable to determine default arrangement\n" );
        return (result);
    }
    result = UF_ASSEM_ask_name_of_arrangement( init_default_arrangement, &init_arrangement_name );
    if (result != 0)
    {
        printf( "Unable to determine name of default arrangement\n" );
        return (result);
    }
    result = UF_ASSEM_ask_arrangements_in_part( part, &n_arrangements, &all_arrangements );
    if (result != 0)
    {
        printf( "Failed to retrieve list of all arrangements in part\n" );
        UF_free( init_arrangement_name );
        return (result);
    }

    if (n_arrangements > 1)
    {
        char    *new_arrangement_name;
        int     i;

        for (i = 0; i < n_arrangements; i++)
        {
            /*  Use the first non-default arrangement */
            if (all_arrangements[i] != init_default_arrangement)
                break;
        }

        result = UF_ASSEM_ask_name_of_arrangement( all_arrangements[i], &new_arrangement_name );
        if (result != 0)
        {
            printf( "Failed to extract name for new default arrangement\n" );
            UF_free( init_arrangement_name );
            UF_free( all_arrangements );
            return (result);
        }

        result = UF_ASSEM_set_default_arrangement( all_arrangements[i] );
        if (result != 0)
        {
            printf( "Failed to change default arrangement from %s to %s\n",
                    init_arrangement_name, new_arrangement_name );
            UF_free( init_arrangement_name );
            UF_free( all_arrangements );
            UF_free( new_arrangement_name );
            return (result);
        }

        printf( "The default arrangement has been changed from %s to %s\n",
                init_arrangement_name, new_arrangement_name );
        UF_free( new_arrangement_name );

    }
    else
    {
        printf( "Only 1 arrangement in the display part, could not change default arrangement from %s\n",
                init_arrangement_name );
    }

    UF_free( init_arrangement_name );
    UF_free( all_arrangements );
    return (result);
}

static int change_used_arrangement_of_components( tag_t component )
{
    int i;
    int result = 0;
    int n_children = 0;
    tag_t *child_components = (tag_t *)NULL_TAG;

    if (component == NULL_TAG) return 0;

    n_children = UF_ASSEM_ask_part_occ_children( component, &child_components);

    /*  For each child of the input component, change the
        used arrangement, then do the same for its children.
    */
    for (i = 0; i < n_children; i++)
    {
        result = change_used_arrangement( child_components[i] );

        result = change_used_arrangement_of_components( child_components[i] );
    }

    UF_free(child_components);

    return result;
}

static int change_used_arrangement( tag_t component )
{
    int     result = 0;
    int     n_arrangements;
    tag_t   init_used_arrangement;
    tag_t   *all_arrangements;
    tag_t   comp_part = UF_ASSEM_ask_prototype_of_occ( component );
    char    *init_arrangement_name;
    char    p_name[MAX_FSPEC_SIZE];
    char    r_name[MAX_ENTITY_NAME_SIZE];
    char    c_name[UF_CFI_MAX_FILE_NAME_SIZE];
    double  origin[3];
    double  csys_matrix[9];
    double  transform[4][4];

    result = UF_ASSEM_ask_component_data( component,p_name,r_name,
                                          c_name,origin,csys_matrix,
                                          transform);


    result = UF_ASSEM_ask_used_arrangement( component, &init_used_arrangement );
    if (result != 0)
    {
        printf( "Unable to determine used arrangement for component %s\n", c_name );
        return (result);
    }
    result = UF_ASSEM_ask_name_of_arrangement( init_used_arrangement, &init_arrangement_name );
    if (result != 0)
    {
        printf( "Unable to determine name of used arrangement for component %s\n", c_name );
        return (result);
    }
    result = UF_ASSEM_ask_arrangements_in_part( comp_part, &n_arrangements, &all_arrangements );
    if (result != 0)
    {
        printf( "Failed to retrieve list of all arrangements in component part %s\n", p_name );
        UF_free( init_arrangement_name );
        return (result);
    }

    if (n_arrangements > 1)
    {
        char    *new_arrangement_name;
        int     i;

        for (i = 0; i < n_arrangements; i++)
        {
            /*  Use the first non-default arrangement */
            if (all_arrangements[i] != init_used_arrangement)
                break;
        }

        result = UF_ASSEM_ask_name_of_arrangement( all_arrangements[i], &new_arrangement_name );
        if (result != 0)
        {
            printf( "Failed to extract name for new used arrangement in component %s\n", c_name );
            UF_free( init_arrangement_name );
            UF_free( all_arrangements );
            return (result);
        }

        result = UF_ASSEM_set_used_arrangement( component, all_arrangements[i] );
        if (result != 0)
        {
            printf( "Failed to change used arrangement from %s to %s for component %s\n",
                    init_arrangement_name, new_arrangement_name, c_name );
            UF_free( init_arrangement_name );
            UF_free( all_arrangements );
            UF_free( new_arrangement_name );
            return (result);
        }

        printf( "The used arrangement for component %s has been changed from %s to %s\n",
                c_name, init_arrangement_name, new_arrangement_name );
        UF_free( new_arrangement_name );

    }
    else
    {
        printf( "Only 1 arrangement in the component part %s, could not change default arrangement from %s\n",
                c_name, init_arrangement_name );
    }

    UF_free( init_arrangement_name );
    UF_free( all_arrangements );
    return (result);
}
