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

             Copyright (c) 2002,2003 Unigraphics Solutions Inc.
                     Unpublished - All rights reserved
================================================================================
File description:

    The following file is a sample file that shows how to create and edit
    image object on a drawing sheet.

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

#include <uf_defs.h>
#include <stdarg.h>
#include <stdio.h>
#include <uf.h>
#include <uf_draw.h>
#include <uf_draw_errors.h>
#include <uf_draw_types.h>
#include <uf_drf.h>
#include <uf_drf_errors.h>
#include <uf_drf_types.h>
#include <uf_part.h>
#include <uf_undo.h>


/*---------------------------------------------------------------------------*
 * Print the error message with the associated error code
 *---------------------------------------------------------------------------*/
static void print_error(
    const char *msg,            /* <I> Message header                   */
    int   error_code,           /* <I> Error code                       */
    const char *format,         /* <I> Format for arguments that follow */
    ...                         /* <I> Arguments for format             */
)
{
    va_list ap;

    if ( error_code == UF_DRF_NO_ERRORS )
        printf( "%s: ", msg );
    else
    {
        char error_msg[MAX_LINE_SIZE + 1];

        UF_get_fail_message( error_code, error_msg );

        printf( "%s: %s\n    ", msg, error_msg );
    }

    va_start( ap, format );

    vprintf( format, ap );

    va_end( ap );

    printf( "\n" );
}

/*---------------------------------------------------------------------------*
 * Create the drawing in which to create images
 *
 * Returns:
 *     UF_DRAW_NO_ERRORS if the drawing was successfully created
 *     != UF_DRAW_NO_ERRORS if no drawing was created
 *---------------------------------------------------------------------------*/
static int create_drawing(
    tag_p_t drawing_tag /* <O> Drawing created or NULL_TAG if error occurred */
)
{
    char *drawing_name = "Test Images";
    int status = UF_DRAW_NO_ERRORS;
    UF_DRAW_info_t drawing_data;

    *drawing_tag = NULL_TAG;

    drawing_data.size_state            = UF_DRAW_METRIC_SIZE;
    drawing_data.size.metric_size_code = UF_DRAW_A1;
    drawing_data.drawing_scale         = 1.0;
    drawing_data.units                 = UF_PART_METRIC;
    drawing_data.projection_angle      = UF_DRAW_THIRD_ANGLE_PROJECTION;

    status = UF_DRAW_create_drawing( drawing_name, &drawing_data, drawing_tag );

    if ( status != UF_DRF_NO_ERRORS )
        print_error( "UF_DRAW_create_drawing", status, "%s", drawing_name );

    return ( status );
}

/*---------------------------------------------------------------------------*
 * Create a image objects on the specified drawing
 *
 * Returns:
 *     UF_DRAW_NO_ERRORS if the drawing was successfully created
 *     != UF_DRAW_NO_ERRORS if no drawing was created
 *---------------------------------------------------------------------------*/
static int create_images(
    char *image_file,  /* <I> Name of image file to create image from */
    tag_t drawing_tag, /* <I> Drawing to create image in              */
    tag_t *image_tag1, /* <O> Image tag created or NULL_TAG if error  */
    tag_t *image_tag2  /* <O> Image tag created or NULL_TAG if error  */
)
{
    int status = UF_DRF_NO_ERRORS;
    int status2 = UF_DRF_NO_ERRORS;
    double origin[3];
    UF_DRF_image_data_t image_data;

    *image_tag1 = NULL_TAG;
    *image_tag2 = NULL_TAG;

    origin[0] = 100.0;
    origin[1] = 100.0;
    origin[2] =   0.0;

    status = UF_DRF_create_image_from_file( image_file, drawing_tag,
                                            origin, image_tag1 );

    if ( status != UF_DRF_NO_ERRORS )
    {
        print_error( "UF_DRF_create_image_from_file", status, "%s", image_file );
        return ( status );
    }

    status = UF_DRF_ask_image_data( *image_tag1, &image_data );

    if ( status != UF_DRF_NO_ERRORS )
    {
        print_error( "UF_DRF_ask_image_data", status, "%u", *image_tag1 );
        return ( status );
    }

    origin[0] += image_data.width;
    origin[1] += image_data.height;
    origin[2]  = 0.0;

    status = UF_DRF_create_image( image_data.image_name, drawing_tag,
                                  origin, image_tag2 );

    if ( status != UF_DRF_NO_ERRORS )
        print_error( "UF_DRF_create_image", status, "%s",
                     image_data.image_name );

    status2 = UF_DRF_free_image_data( &image_data );

    if ( status2 != UF_DRF_NO_ERRORS )
        print_error( "UF_DRF_free_image_data", status2, "" );

    return ( status );
}

/*---------------------------------------------------------------------------*
 * Edit an image object
 *
 * Returns:
 *     UF_DRAW_NO_ERRORS if the drawing was successfully created
 *     != UF_DRAW_NO_ERRORS if no drawing was created
 *---------------------------------------------------------------------------*/
static int edit_image(
    tag_t image_tag  /* <I> Image tag edit */
)
{
    int status = UF_DRF_NO_ERRORS;
    int status2 = UF_DRF_NO_ERRORS;
    UF_DRF_image_data_t image_data;

    status = UF_DRF_ask_image_data( image_tag, &image_data );

    if ( status != UF_DRF_NO_ERRORS )
    {
        print_error( "UF_DRF_ask_image_data", status, "(%u)", image_tag );
        return ( status );
    }

    /* Make sure that the image's aspect ratio is not locked so that we
     * can edit the image height without causing its width to change
     */
    status = UF_DRF_set_image_aspect_ratio_lock( image_tag, FALSE );

    if ( status != UF_DRF_NO_ERRORS )
        print_error( "UF_DRF_set_image_aspect_ratio_lock", status,
                     "(%u, FALSE)", image_tag );

    /* Double the image height */
    if ( status == UF_DRF_NO_ERRORS )
    {
        status = UF_DRF_set_image_height( image_tag, 2.0 * image_data.height );

        if ( status != UF_DRF_NO_ERRORS )
            print_error( "UF_DRF_set_image_height", status,
                         "(%u, %g)", image_tag, 2.0 * image_data.height );
    }

    /* Set the image's alignment position to the bottom right corner */
    if ( status == UF_DRF_NO_ERRORS )
    {
        status = UF_DRF_set_image_align_position( image_tag,
                                                  UF_DRF_ALIGN_BOTTOM_RIGHT );

        if ( status != UF_DRF_NO_ERRORS )
            print_error( "UF_DRF_set_image_align_position", status,
                         "(%u, UF_DRF_ALIGN_BOTTOM_RIGHT)", image_tag );
    }

    /* Move the image along the drawing's X-axis */
    if ( status == UF_DRF_NO_ERRORS )
    {
        image_data.origin[0] += 10.0;

        status = UF_DRF_set_origin( image_tag, image_data.origin );

        if ( status != UF_DRF_NO_ERRORS )
            print_error( "UF_DRF_set_origin", status,
                         "(%u, (%g, %g, %g))", image_tag,
                         image_data.origin[0], image_data.origin[1],
                         image_data.origin[2] );
    }

    /* Rotate the image 90 degrees counter-clockwise */
    if ( status == UF_DRF_NO_ERRORS )
    {
        image_data.origin[0] += 10.0;

        status = UF_DRF_rotate_image( image_tag, 90.0 );

        if ( status != UF_DRF_NO_ERRORS )
            print_error( "UF_DRF_rotate_image", status,
                         "(%u, 90.0)", image_tag );
    }

    /* Flip the image about the direction of its width */
    if ( status == UF_DRF_NO_ERRORS )
    {
        status = UF_DRF_flip_image_about_width( image_tag );

        if ( status != UF_DRF_NO_ERRORS )
            print_error( "UF_DRF_flip_image_about_width", status,
                         "(%u)", image_tag );
    }

    status2 = UF_DRF_free_image_data( &image_data );

    if ( status2 != UF_DRF_NO_ERRORS )
        print_error( "UF_DRF_free_image_data", status2, "" );

    return ( status );
}

/*---------------------------------------------------------------------------*
 * Create a drawing and add images to it, then edit one of the images
 *---------------------------------------------------------------------------*/
static int create_drawing_and_images( void )
{
    char *image_name = "ufd_drf_image.jpg";
    int status = UF_DRF_NO_ERRORS;
    tag_t drawing_tag, image_tag1, image_tag2;

    status = create_drawing( &drawing_tag );
    if ( status != UF_DRF_NO_ERRORS )
        return ( status );

    status = create_images( image_name, drawing_tag, &image_tag1, &image_tag2 );
    if ( status != UF_DRF_NO_ERRORS )
        return ( status );

    status = edit_image( image_tag2 );

    return ( status );
}

/*---------------------------------------------------------------------------*
 * Create a part and add images to its drawing
 *---------------------------------------------------------------------------*/
static int create_part_with_images( void )
{
    int status, term_status;
    char *part_name = "my_image_part";
    tag_t part_tag = NULL_TAG;

    status = UF_initialize();

    if ( status != UF_DRF_NO_ERRORS )
    {
        print_error( "UF_initialize", status, "Aborting..." );
        return ( status );
    }

    status = UF_PART_new( part_name, 1, &part_tag );

    if ( status != UF_DRF_NO_ERRORS )
        print_error( "UF_PART_new", status, "%s", part_name );

    if ( status == UF_DRF_NO_ERRORS )
    {
        UF_UNDO_mark_id_t mark_id;

        status = UF_UNDO_set_mark( UF_UNDO_visible, "New Part", &mark_id );

        if ( status != UF_DRF_NO_ERRORS )
            print_error( "UF_UNDO_set_mark", status, "New Part" );
    }

    if ( status == UF_DRF_NO_ERRORS )
        status = create_drawing_and_images();

    if ( status == UF_DRF_NO_ERRORS )
    {
        status = UF_PART_save();

        if ( status != UF_DRF_NO_ERRORS )
            print_error( "UF_PART_save", status, "%s", part_name );
    }

    term_status = UF_terminate();

    if ( term_status != UF_DRF_NO_ERRORS )
    {
        print_error( "UF_terminate", term_status, "" );

        if ( status == UF_DRF_NO_ERRORS )
            status = term_status;
    }

    return ( status );
}

/*---------------------------------------------------------------------------*
 * Internal user function that creates and edits images
 *
 * Input Arguments: None
 *---------------------------------------------------------------------------*/
extern void ufusr(
   char  *param,                /* <I> Unused */
   int   *irc,                  /* <I> Unused */
   int    param_len             /* <I> Unused */
)
{
    create_part_with_images();
}

/*---------------------------------------------------------------------------*
 * External user function that creates and edits images
 *
 * Call Syntax:
 *     external_ufun_program
 *
 * Input Arguments: None
 *---------------------------------------------------------------------------*/
extern int main(
    int    argc,                /* <I> Number of input arguments */
    char **argv                 /* <I> List of input arguments   */
)
{
    return ( create_part_with_images() );
}