/*
 * Go2Measurement.c
 * 
 * Gocator system communication library
 * Copyright (C) 2010 by LMI Technologies Inc.
 * 
 * Licensed under The MIT License.
 * Redistributions of files must retain the above copyright notice.
 */
#include <z/zGo2Measurement.h>
#include <z/zGo2System.h>
#include <z/zGo2Api.h>
#include <string.h>

GO2_EXPORT(Go2Status) Go2Measurement_Init(Go2Measurement measurement, Go2Type type, Go2UInt32 id, Go2System system)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2Object_Init(measurement, type)); 

    obj->Release = Go2Measurement_VRelease; 
    obj->Read = Go2Measurement_VRead; 
    obj->Write = Go2Measurement_VWrite; 

    GO2_CHECK(zList_Construct(&obj->sourceOptions, sizeof(z32s), 0)); 
    GO2_CHECK(zList_Construct(&obj->linkableIds, sizeof(z32s), 0)); 

    obj->id = id; 
    obj->system = system; 

    obj->scale = 1.0;   
        //while every other option can be 0, the scale factor should not be 0 by default.
    
    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2Measurement_VRelease(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(zList_Destroy(obj->sourceOptions)); 
    GO2_CHECK(zList_Destroy(obj->linkableIds)); 

    return Go2Object_VRelease(measurement); 
}

GO2_EXPORT(Go2Status) Go2Measurement_Read(Go2Measurement measurement, zXml xml, zXmlItem item)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->Read(measurement, xml, item); 
}

GO2_EXPORT(Go2Status) Go2Measurement_Write(Go2Measurement measurement, zXml xml, zXmlItem item)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->Write(measurement, xml, item); 
}

GO2_EXPORT(Go2Status) Go2Measurement_VRead(Go2Measurement measurement, zXml xml, zXmlItem item)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    zChar* text = zNULL;
    z32u textCapacity = GO2_MEASUREMENT_SOURCE_TEXT_CAPACITY; 

    zEXCEPT_TRY
    {
        zEXCEPT_CHECK(zXml_Attr32u(xml, item, "id", &obj->id)); 

        zEXCEPT_CHECK(zXml_ChildText(xml, item, "Name", obj->name, zCOUNT(obj->name))); 

        GO2_CHECK(zXml_Child32u(xml, item, "Link", &obj->link)); 
        GO2_CHECK(zXml_Child32s(xml, item, "LinkEnabled", &obj->linkEnabled)); 

        zCHECK(zCalloc(&text, textCapacity, sizeof(zChar)));
        if (zXml_ChildText(xml, item, "LinkIds", text, textCapacity) == GO2_OK)
        {
            zCHECK(Go2OptionList_ParseList(text, obj->linkableIds));  
        }

        zEXCEPT_CHECK(zXml_Child64f(xml, item, "DecisionMin", &obj->decisionMin)); 
        zEXCEPT_CHECK(zXml_Child64f(xml, item, "DecisionMax", &obj->decisionMax)); 

        zEXCEPT_CHECK(zXml_Child64f(xml, item, "Scale", &obj->scale)); 
        zEXCEPT_CHECK(zXml_Child64f(xml, item, "Offset", &obj->offset)); 
        zEXCEPT_CHECK(zXml_Child32s(xml, item, "HoldEnabled", &obj->holdEnabled)); 
        zEXCEPT_CHECK(zXml_Child32s(xml, item, "SmoothingEnabled", &obj->smoothingEnabled));
        zEXCEPT_CHECK(zXml_Child32u(xml, item, "SmoothingWindowMin", &obj->smoothingWindowMin)); 
        zEXCEPT_CHECK(zXml_Child32u(xml, item, "SmoothingWindowMax", &obj->smoothingWindowMax)); 
        zEXCEPT_CHECK(zXml_Child32u(xml, item, "SmoothingWindow", &obj->smoothingWindow)); 
    }
    zEXCEPT_CATCH(zNULL) {}
    zEXCEPT_FINALLY
    {
        zFree(text);
        zEXCEPT_CLOSE(); 
    }

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2Measurement_VWrite(Go2Measurement measurement, zXml xml, zXmlItem item)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(zXml_SetAttr32u(xml, item, "id", obj->id)); 

    GO2_CHECK(zXml_SetChildText(xml, item, "Name", obj->name)); 

    GO2_CHECK(zXml_SetChild32u(xml, item, "Link", obj->link)); 
    GO2_CHECK(zXml_SetChild32s(xml, item, "LinkEnabled", obj->linkEnabled)); 

    GO2_CHECK(zXml_SetChild64f(xml, item, "DecisionMin", obj->decisionMin)); 
    GO2_CHECK(zXml_SetChild64f(xml, item, "DecisionMax", obj->decisionMax)); 

    GO2_CHECK(zXml_SetChild64f(xml, item, "Scale", obj->scale)); 
    GO2_CHECK(zXml_SetChild64f(xml, item, "Offset", obj->offset)); 
    GO2_CHECK(zXml_SetChild32s(xml, item, "HoldEnabled", obj->holdEnabled)); 
    GO2_CHECK(zXml_SetChild32s(xml, item, "SmoothingEnabled", obj->smoothingEnabled)); 
    GO2_CHECK(zXml_SetChild32u(xml, item, "SmoothingWindow", obj->smoothingWindow)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2Measurement_SetId(Go2Measurement measurement, Go2UInt32 id)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
   
    GO2_CHECK(Go2System_Set32u(obj->system, &obj->id, id, z32U_MIN, z32U_MAX));
    GO2_CHECK(Go2System_SyncConfig(obj->system)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2UInt32) Go2Measurement_Id(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->id; 
}

GO2_EXPORT(Go2Status) Go2Measurement_SetName(Go2Measurement measurement, const Go2Char* name)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return Go2System_SetText(obj->system, obj->name, zCOUNT(obj->name), name); 
}

GO2_EXPORT(Go2Status) Go2Measurement_Name(Go2Measurement measurement, Go2Char* name, Go2UInt32 capacity)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    strncpy(name, obj->name, capacity); 
    name[capacity-1] = 0; 

    return GO2_OK; 
}

GO2_EXPORT(Go2UInt32) Go2Measurement_SourceOptionCount(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return zList_Count(obj->sourceOptions);
}

GO2_EXPORT(Go2UInt32) Go2Measurement_SourceOptionAt(Go2Measurement measurement, Go2UInt32 index)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    z32u* option = zList_At(obj->sourceOptions, index); 
    return !zIS_NULL(option) ? *option : 0; 
}

GO2_EXPORT(Go2Status) Go2Measurement_SetSource(Go2Measurement measurement, Go2UInt32 source)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->source = source; 
    GO2_CHECK(Go2System_SetModified(obj->system)); 

    return GO2_OK;
}

GO2_EXPORT(Go2UInt32) Go2Measurement_Source(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->source; 
}

GO2_EXPORT(Go2Status) Go2Measurement_SetDecisionMin(Go2Measurement measurement, Go2Double min)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    
    GO2_CHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->decisionMin = min; 
    GO2_CHECK(Go2System_SetModified(obj->system)); 

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Measurement_DecisionMin(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->decisionMin;
}

GO2_EXPORT(Go2Status) Go2Measurement_SetDecisionMax(Go2Measurement measurement, Go2Double max)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->decisionMax = max; 
    GO2_CHECK(Go2System_SetModified(obj->system)); 

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Measurement_DecisionMax(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->decisionMax;
}

GO2_EXPORT(Go2Status) Go2Measurement_SetScale(Go2Measurement measurement, Go2Double scale)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(Go2System_CheckConfigurable(obj->system));
    obj->scale = scale;
    GO2_CHECK(Go2System_SetModified(obj->system));
    
    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Measurement_Scale(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement);
    return obj->scale;
}

GO2_EXPORT(Go2Status) Go2Measurement_SetOffset(Go2Measurement measurement, Go2Double offset)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(Go2System_CheckConfigurable(obj->system));
    obj->offset = offset;
    GO2_CHECK(Go2System_SetModified(obj->system));
    
    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Measurement_Offset(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement);
    return obj->scale;
}

GO2_EXPORT(Go2Status) Go2Measurement_EnableHold(Go2Measurement measurement, Go2Bool enable)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->holdEnabled = enable; 
    GO2_CHECK(Go2System_SetModified(obj->system)); 

    return GO2_OK;
} 

GO2_EXPORT(Go2Bool) Go2Measurement_HoldEnabled(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->holdEnabled;
}

GO2_EXPORT(Go2Status) Go2Measurement_EnableSmoothing(Go2Measurement measurement, Go2Bool enable)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->smoothingEnabled = enable; 
    GO2_CHECK(Go2System_SetModified(obj->system)); 

    return GO2_OK;
} 

GO2_EXPORT(Go2Bool) Go2Measurement_SmoothingEnabled(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->smoothingEnabled;
} 

GO2_EXPORT(Go2UInt32) Go2Measurement_SmoothingWindowMin(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->smoothingWindowMin;
} 

GO2_EXPORT(Go2UInt32) Go2Measurement_SmoothingWindowMax(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->smoothingWindowMax;
} 

GO2_EXPORT(Go2Status) Go2Measurement_SetSmoothingWindow(Go2Measurement measurement, Go2UInt32 window)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2System_Set32u(obj->system, &obj->smoothingWindow, window, obj->smoothingWindowMin, obj->smoothingWindowMax));

    return GO2_OK;
} 

GO2_EXPORT(Go2UInt32) Go2Measurement_SmoothingWindow(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->smoothingWindow;
} 

/*
 * Go2PartMeasurement Class 
 */

GO2_EXPORT(Go2Status) Go2PartMeasurement_Init(Go2PartMeasurement measurement, Go2Type type, Go2UInt32 id, Go2System system)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2Measurement_Init(measurement, type, id, system));

    obj->Read = Go2PartMeasurement_VRead; 
    obj->Write = Go2PartMeasurement_VWrite; 
    obj->Release = Go2PartMeasurement_VRelease;

    GO2_CHECK(Go2PartRegion3d_Construct(&obj->region, system));
    obj->regionEnabled = GO2_FALSE;

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2PartMeasurement_VRelease(Go2PartMeasurement measurement)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2Object_Destroy(obj->region));

    GO2_CHECK(Go2Measurement_VRelease(measurement));

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2PartMeasurement_Read(Go2PartMeasurement measurement, zXml xml, zXmlItem item)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->Read(measurement, xml, item); 
}

GO2_EXPORT(Go2Status) Go2PartMeasurement_Write(Go2PartMeasurement measurement, zXml xml, zXmlItem item)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return obj->Write(measurement, xml, item); 
}

GO2_EXPORT(Go2Status) Go2PartMeasurement_VRead(Go2PartMeasurement measurement, zXml xml, zXmlItem item)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement); 
    zXmlItem regionItem = zNIL;

    GO2_CHECK(Go2Measurement_VRead(measurement, xml, item)); 

    if (obj->type != GO2_TYPE_PART_PLANE_X_ANGLE
        && obj->type != GO2_TYPE_PART_PLANE_Y_ANGLE
        && obj->type != GO2_TYPE_PART_PLANE_Z_OFFSET
        && obj->type != GO2_TYPE_PART_POSITION_X
        && obj->type != GO2_TYPE_PART_POSITION_Y
        && obj->type != GO2_TYPE_PART_POSITION_Z
        && obj->type != GO2_TYPE_PART_TEXTURE_ROUGHNESS
        && obj->type != GO2_TYPE_PART_TEXTURE_INVALID_COUNT)
    {
        GO2_CHECK(zXml_Child32s(xml, item, "RegionEnabled", &obj->regionEnabled)); 
        GO2_CHECK(!zIS_NIL(regionItem = zXml_Child(xml, item, "Region")));    
        GO2_CHECK(Go2PartRegion3d_Read(obj->region, xml, regionItem));  
    }

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2PartMeasurement_VWrite(Go2PartMeasurement measurement, zXml xml, zXmlItem item)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement); 
    zXmlItem regionItem = zNIL;

    GO2_CHECK(Go2Measurement_VWrite(measurement, xml, item)); 

    if (obj->type != GO2_TYPE_PART_PLANE_X_ANGLE
        && obj->type != GO2_TYPE_PART_PLANE_Y_ANGLE
        && obj->type != GO2_TYPE_PART_PLANE_Z_OFFSET
        && obj->type != GO2_TYPE_PART_POSITION_X
        && obj->type != GO2_TYPE_PART_POSITION_Y
        && obj->type != GO2_TYPE_PART_POSITION_Z
        && obj->type != GO2_TYPE_PART_TEXTURE_ROUGHNESS
        && obj->type != GO2_TYPE_PART_TEXTURE_INVALID_COUNT)
    {
        GO2_CHECK(zXml_SetChild32s(xml, item, "RegionEnabled", obj->regionEnabled)); 
        GO2_CHECK(zXml_AddItem(xml, item, "Region", &regionItem));  
        GO2_CHECK(Go2PartRegion3d_Write(obj->region, xml, regionItem));  
    }
    
    return GO2_OK; 
}

GO2_EXPORT(Go2UInt32) Go2Measurement_LinkOptionCount(Go2Measurement measurement)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    return zList_Count(obj->linkableIds);
}

GO2_EXPORT(Go2UInt32) Go2Measurement_LinkOptionAt(Go2Measurement measurement, Go2UInt32 index)
{
    Go2MeasurementClass* obj = zHANDLE_POINTER(measurement); 
    z32u* option = zList_At(obj->linkableIds, index); 
    return !zIS_NULL(option) ? *option : 0; 
}

GO2_EXPORT(Go2Status) Go2Measurement_EnableLink( Go2Measurement measurement, Go2Bool enable )
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(Go2System_CheckConfigurable(obj->system));
    obj->linkEnabled = enable;
    GO2_CHECK(Go2System_SetModified(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Bool) Go2Measurement_LinkEnabled( Go2Measurement measurement )
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement);

    return obj->linkEnabled;
}

GO2_EXPORT(Go2Status) Go2Measurement_SetLink( Go2Measurement measurement, Go2UInt32 link )
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(Go2System_CheckConfigurable(obj->system));
    obj->link = link;
    GO2_CHECK(Go2System_SetModified(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2UInt32) Go2Measurement_Link( Go2Measurement measurement )
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement);

    return obj->link;
}

GO2_EXPORT(Go2Status) Go2PartMeasurement_EnableRegion(Go2PartMeasurement measurement, Go2Bool enable)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(Go2System_CheckConfigurable(obj->system));
    obj->regionEnabled = enable;
    GO2_CHECK(Go2System_SetModified(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Bool) Go2PartMeasurement_RegionEnabled(Go2PartMeasurement measurement)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement);

    return obj->regionEnabled;
}

GO2_EXPORT(Go2PartRegion3d) Go2PartMeasurement_Region(Go2PartMeasurement measurement)
{
    Go2PartMeasurementClass* obj = zHANDLE_POINTER(measurement);

    return obj->region;
}

/*
 * Go2Script Class 
 */

GO2_EXPORT(Go2Status) Go2Script_Construct(Go2Script* measurement, Go2UInt32 id, Go2Object system)
{
    Go2Script output = zNIL; 
    Go2Status status = zOK; 

    GO2_CHECK(zCalloc(&output, 1, sizeof(Go2ScriptClass))); 

    if (!zSUCCESS(status = Go2Script_Init(output, id, system)))
    {
        GO2_CHECK(Go2Object_Destroy(output)); 
    }

    *measurement = output; 

    return status; 
}

GO2_EXPORT(Go2Status) Go2Script_Init(Go2Script measurement, Go2UInt32 id, Go2Object system)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(Go2Measurement_Init(measurement, GO2_TYPE_SCRIPT, id, system)); 
    
    obj->Release = Go2Script_VRelease; 
    obj->Read = Go2Script_VRead; 
    obj->Write = Go2Script_VWrite; 

    GO2_CHECK(zCalloc(&obj->sourceCode, 1, sizeof(zChar)));  
    GO2_CHECK(zList_Construct(&obj->outputList, sizeof(Go2UInt32), 0));
    GO2_CHECK(zList_Add(obj->outputList, &obj->id));

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2Script_VRelease(Go2Script measurement)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(zFree(obj->sourceCode)); 

    GO2_CHECK(zList_Destroy(obj->outputList));
    GO2_CHECK(Go2Measurement_VRelease(measurement)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2Script_VRead(Go2Script measurement, zXml xml, zXmlItem item)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);
    Go2UInt32 currentId;
    zText256 outputList = "";
    zChar* currentToken;
    Go2Bool firstToken = GO2_TRUE;
    
    GO2_CHECK(zList_Clear(obj->outputList));
    GO2_CHECK(zXml_AttrText(xml, item, "id", outputList, 256)); 

    currentToken = strtok(outputList, ",");

    while (currentToken != NULL)
    {
        sscanf(currentToken, "%u", &currentId);

        if (firstToken)
        {
            obj->id = currentId;
            firstToken = GO2_FALSE;
        }
        
        GO2_CHECK(zList_Add(obj->outputList, &currentId));
        currentToken = strtok(NULL, ",");
    }
    
    if (zList_Count(obj->outputList) == 0)
    {
        return GO2_ERROR_PARAMETER;
    }

    GO2_CHECK(zXml_ChildText(xml, item, "Name", obj->name, zCOUNT(obj->name))); 

    GO2_CHECK(zFree(obj->sourceCode)); 
    obj->sourceCode = zNULL; 
    GO2_CHECK(zXml_ChildString(xml, item, "Code", &obj->sourceCode)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2Script_VWrite(Go2Script  measurement, zXml xml, zXmlItem item)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);
    z32u i;
    zText256 outputList = "";
    zChar currentId[12];
    
    for (i = 0; i < zList_Count(obj->outputList); i++)
    {
        sprintf(currentId, "%u", *(z32u*)zList_At(obj->outputList, i));
        
        strcat(outputList, currentId);

        if (i != (zList_Count(obj->outputList) - 1))
        {
            strcat(outputList, ",");
        }
    }

    GO2_CHECK(zXml_SetAttrText(xml, item, "id", outputList)); 

    GO2_CHECK(zXml_SetChildText(xml, item, "Name", obj->name)); 
    GO2_CHECK(zXml_SetChildText(xml, item, "Code", obj->sourceCode)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2Script_SetId(Go2Script measurement, Go2UInt32 id)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(Go2System_CheckConfigurable(obj->system));

    *(z32u*)zList_At(obj->outputList, 0) = id;
    obj->id = id;

    GO2_CHECK(Go2System_SetModified(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Script_Id(Go2Script measurement)
{
    return Go2Measurement_Id(measurement); 
}

GO2_EXPORT(Go2Status) Go2Script_SetName(Go2Script measurement, const Go2Char* name)
{
    return Go2Measurement_SetName(measurement, name); 
}

GO2_EXPORT(Go2Status) Go2Script_Name(Go2Script measurement, Go2Char* name, Go2UInt32 capacity)
{
    return Go2Measurement_Name(measurement, name, capacity); 
}

GO2_EXPORT(Go2Status) Go2Script_AddOutput( Go2Script measurement, Go2UInt32 id )
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);
    Go2UInt32 i;

    GO2_CHECK(Go2System_CheckConfigurable(obj->system));

    for (i = 0; i < zList_Count(obj->outputList); i++)
    {
        if (id == *(z32u*)zList_At(obj->outputList, i))
        {
            return GO2_ERROR_PARAMETER;
        }
    }

    GO2_CHECK(zList_Add(obj->outputList, &id));
    GO2_CHECK(Go2System_SetModified(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2UInt32) Go2Script_OutputCount(Go2Script measurement)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);

    return zList_Count(obj->outputList);
}

GO2_EXPORT(Go2Status) Go2Script_RemoveOutputAt( Go2Script measurement, Go2UInt32 index)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);
    
    GO2_CHECK(Go2System_CheckConfigurable(obj->system));
    if (index > zList_Count(obj->outputList)
        || zList_Count(obj->outputList) == 1)
    {
        return GO2_ERROR_PARAMETER;
    }

    GO2_CHECK(zList_Remove(obj->outputList, index, GO2_NULL));
    GO2_CHECK(Go2System_SetModified(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Script_FindOutputIndex(Go2Script measurement, Go2UInt32 id, Go2UInt32* index)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);
    Go2UInt32 i;

    for (i = 0; i < zList_Count(obj->outputList); i++)
    {
        if (id == *(Go2UInt32*)zList_At(obj->outputList, i))
        {
            *index = id;

            return GO2_OK;
        }
    }

    return GO2_ERROR_PARAMETER;
}

GO2_EXPORT(Go2Status) Go2Script_SetOutputIdAt(Go2Script measurement, Go2UInt32 index, Go2UInt32 id)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);

    GO2_CHECK(Go2System_CheckConfigurable(obj->system));

    if (index >= zList_Count(obj->outputList))
    {
        return GO2_ERROR_PARAMETER;
    }

    *(z32u*)zList_At(obj->outputList, index) = id;

    GO2_CHECK(Go2System_SetModified(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Script_OutputIdAt(Go2Script measurement, Go2UInt32 index, Go2UInt32* id)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement);

    if (index >= zList_Count(obj->outputList))
    {
        return GO2_ERROR_PARAMETER;
    }

    *id = *(z32u*)zList_At(obj->outputList, index);
    
    return GO2_OK;
        
}

GO2_EXPORT(Go2Status) Go2Script_SetCode(Go2Script measurement, const Go2Char* sourceCode)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement); 

    GO2_CHECK(Go2System_CheckConfigurable(obj->system)); 

    if (!zIS_NULL(sourceCode))
    {
        z32u length = (z32u) strlen(sourceCode); 

        GO2_CHECK(zFree(obj->sourceCode)); 
        GO2_CHECK(zCalloc(&obj->sourceCode, length + 1, sizeof(zChar))); 
        strcpy(obj->sourceCode, sourceCode); 
    }
    else
    {
        GO2_CHECK(zFree(obj->sourceCode)); 
        GO2_CHECK(zCalloc(&obj->sourceCode, 1, sizeof(zChar))); 
    }

    GO2_CHECK(Go2System_SyncConfig(obj->system)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2Script_Code(Go2Script measurement, Go2Char** sourceCode)
{
    Go2ScriptClass* obj = zHANDLE_POINTER(measurement); 
    z32u length = (z32u) strlen(obj->sourceCode); 
    zChar* output = zNULL; 

    GO2_CHECK(zCalloc(&output, length+1, sizeof(zChar))); 
    strcpy(output, obj->sourceCode); 

    *sourceCode = output; 

    return GO2_OK; 
}
