/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mas_api_internal.h"
#include "mas_getset.h"

#define DEFAULT_PACKAGE_SIZE 1024

int32
mas_mc_add_fixed_clock( char *name, double freq, mas_channel_t channel )
{
    struct mas_package  ppkg;
    struct mas_package  rpkg;
    struct mas_event    event;
    char pbuf[DEFAULT_PACKAGE_SIZE];
    int32 err, clkid;
    
    masc_setup_event( &event );
    event.action_name = "mas_mc_add_fixed_clock";
    
    /* stuff the predicate package */
    masc_setup_package( &ppkg, pbuf, sizeof pbuf, MASC_PACKAGE_STATIC );
    masc_pushk_string( &ppkg, "clock", name );
    masc_pushk_double( &ppkg, "freq", freq );
    masc_finalize_package( &ppkg );
    event.predicate = ppkg.contents;
    event.predicate_length = ppkg.size;
    event.device_instance = MAS_MC_INSTANCE;
    
    /* package & send event to server */
    mas_send_event( &event, channel );
    masc_strike_package( &ppkg );
    
    /* wait for the reply, then form into package */
    err = mas_recv_package( channel, &rpkg );
    if ( err < 0 ) return err;

    /* grab the device instance */
    err = 0;
    masc_pull_int32( &rpkg, &clkid );
    masc_strike_package( &rpkg );

    if ( clkid < 0 ) return clkid;
    
    /* this mess is to ensure that the clock we created above gets
       taken away when the client exits */ 
    {
        struct mas_package lppkg;
        struct mas_event levent;
        char pbuf2[4096];
            
        /*** queue the mas_interact_leave event, for when the client exits */
        masc_setup_event( &levent );
        levent.action_name = "mas_mc_delete_clock";
        levent.device_instance = MAS_MC_INSTANCE;
        
        /* stuff the mas_interact_leave predicate package */
        masc_setup_package( &lppkg, pbuf2, sizeof pbuf2, MASC_PACKAGE_STATIC );
        masc_pushk_int32( &lppkg, "clkid", clkid );
        masc_finalize_package( &lppkg );
        levent.predicate = lppkg.contents;
        levent.predicate_length = lppkg.size;
        /* levent now contains the mas_mc_delete_clock event */
        
        /* Put the mas_mc_delete_clock event in the tracking
           assemblage's terminate event queue */
        masc_setup_event( &event );
        event.action_name = "mas_asm_add_tracking_assemblage_terminate_event";
        event.device_instance = MAS_ASM_INSTANCE;
        
        /* make a package from levent and put in the predicate of the
         * tracking assemblage's terminate event  */
        masc_setup_package( &ppkg, pbuf, sizeof pbuf, MASC_PACKAGE_STATIC );
        masc_pack_event( &ppkg, &levent );
        masc_finalize_package( &ppkg );
        event.predicate = ppkg.contents;
        event.predicate_length = ppkg.size;        

        /* package & send event to server */
        mas_send_event( &event, channel );
        masc_strike_package( &ppkg );
        masc_strike_package( &lppkg );
            
        /* wait for the reply, then form into package */
        err = mas_recv_package( channel, &rpkg );
        if ( err < 0 ) return err;
            
        err = mas_error(MERR_NOTDEF);
        
        if ( masc_test_key( &rpkg, "err" ) == 0 )
            masc_pullk_int32( &rpkg, "err", &err );
            
        masc_strike_package( &rpkg );       
    }

    if ( err < 0 ) return err;

    return clkid;
}
