/*
 * Go2ProfileTypes.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/zGo2ProfileTypes.h>
#include <z/zGo2System.h>
#include <string.h>

/*
 * Go2ProfileArea Class 
 */

GO2_EXPORT(Go2Status) Go2ProfileArea_Construct(Go2ProfileArea* area, Go2System system)
{
    Go2ProfileArea output = zNIL; 
    Go2Status status = GO2_OK; 

    zCHECK(zCalloc(&output, 1, sizeof(Go2ProfileAreaClass))); 

    if (!zSUCCESS(status = Go2ProfileArea_Init(output, system)))
    {
        zCHECK(Go2Object_Destroy(output)); 
        return status; 
    }
    
    *area= output; 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileArea_Init(Go2ProfileArea area, Go2System system)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);

    zCHECK(Go2Object_Init(area, GO2_TYPE_PROFILE_AREA)); 

    obj->system = system; 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileArea_Read(Go2ProfileArea area, zXml xml, zXmlItem item)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);

    zCHECK(zXml_Child64f(xml, item, "X", &obj->x)); 
    zCHECK(zXml_Child64f(xml, item, "Z", &obj->z)); 
    zCHECK(zXml_Child64f(xml, item, "Width", &obj->width)); 
    zCHECK(zXml_Child64f(xml, item, "Height", &obj->height));

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileArea_Write(Go2ProfileArea area, zXml xml, zXmlItem item)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);

    zCHECK(zXml_SetChild64f(xml, item, "X", obj->x)); 
    zCHECK(zXml_SetChild64f(xml, item, "Z", obj->z)); 
    zCHECK(zXml_SetChild64f(xml, item, "Width", obj->width)); 
    zCHECK(zXml_SetChild64f(xml, item, "Height", obj->height));

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileArea_SetX(Go2ProfileArea area, Go2Double x)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);
    return Go2System_Set64f(obj->system,  &obj->x, x, -z64F_MAX, z64F_MAX);     
}

GO2_EXPORT(Go2Double) Go2ProfileArea_X(Go2ProfileArea area)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);
    return obj->x; 
}

GO2_EXPORT(Go2Status) Go2ProfileArea_SetZ(Go2ProfileArea area, Go2Double z)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);
    return Go2System_Set64f(obj->system,  &obj->z, z, -z64F_MAX, z64F_MAX);     
}

GO2_EXPORT(Go2Double) Go2ProfileArea_Z(Go2ProfileArea area)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);
    return obj->z; 
}

GO2_EXPORT(Go2Status) Go2ProfileArea_SetWidth(Go2ProfileArea area, Go2Double width)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);
    return Go2System_Set64f(obj->system,  &obj->width, width, -z64F_MAX, z64F_MAX);     
}

GO2_EXPORT(Go2Double) Go2ProfileArea_Width(Go2ProfileArea area)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);
    return obj->width; 
}

GO2_EXPORT(Go2Status) Go2ProfileArea_SetHeight(Go2ProfileArea area, Go2Double height)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);
    return Go2System_Set64f(obj->system,  &obj->height, height, -z64F_MAX, z64F_MAX);     
}

GO2_EXPORT(Go2Double) Go2ProfileArea_Height(Go2ProfileArea area)
{
    Go2ProfileAreaClass* obj = zHANDLE_POINTER(area);
    return obj->height; 
}

/*
 * Go2ProfileFeature Class 
 */

GO2_EXPORT(Go2Status) Go2ProfileFeature_Construct(Go2ProfileFeature* feature, Go2System system)
{
    Go2ProfileFeature output = zNIL; 
    Go2Status status = GO2_OK; 

    zCHECK(zCalloc(&output, 1, sizeof(Go2ProfileFeatureClass))); 

    if (!zSUCCESS(status = Go2ProfileFeature_Init(output, system)))
    {
        zCHECK(Go2Object_Destroy(output)); 
        return status; 
    }
    
    *feature = output; 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileFeature_Init(Go2ProfileFeature feature, Go2System system)
{
    Go2ProfileFeatureClass* obj = zHANDLE_POINTER(feature);

    zCHECK(Go2Object_Init(feature, GO2_TYPE_PROFILE_FEATURE)); 

    obj->Release = Go2ProfileFeature_VRelease; 
    obj->system = system; 

    zCHECK(Go2ProfileArea_Construct(&obj->area, system)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileFeature_VRelease(Go2ProfileFeature feature)
{
    Go2ProfileFeatureClass* obj = zHANDLE_POINTER(feature);

    zCHECK(Go2Object_Destroy(obj->area)); 

    zCHECK(Go2Object_VRelease(feature)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileFeature_Read(Go2ProfileFeature feature, zXml xml, zXmlItem item)
{
    Go2ProfileFeatureClass* obj = zHANDLE_POINTER(feature);
    zXmlItem areaItem = zNIL; 

    zCHECK(zXml_Child32s(xml, item, "Type", (z32s*) &obj->featureType)); 

    zCHECK(!zIS_NIL(areaItem = zXml_Child(xml, item, "Area"))); 
    zCHECK(Go2ProfileArea_Read(obj->area, xml, areaItem));  

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileFeature_Write(Go2ProfileFeature feature, zXml xml, zXmlItem item)
{
    Go2ProfileFeatureClass* obj = zHANDLE_POINTER(feature);
    zXmlItem areaItem = zNIL; 

    zCHECK(zXml_SetChild32s(xml, item, "Type", obj->featureType)); 

    zCHECK(zXml_AddItem(xml, item, "Area", &areaItem)); 
    zCHECK(Go2ProfileArea_Write(obj->area, xml, areaItem));  

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileFeature_SetType(Go2ProfileFeature feature, Go2ProfileFeatureType type)
{
    Go2ProfileFeatureClass* obj = zHANDLE_POINTER(feature);
    return Go2System_Set32s(obj->system, (Go2Int32*) &obj->featureType, type, -z32S_MAX, z32S_MAX);     
}

GO2_EXPORT(Go2ProfileFeatureType) Go2ProfileFeature_Type(Go2ProfileFeature feature)
{
    Go2ProfileFeatureClass* obj = zHANDLE_POINTER(feature);
    return obj->featureType; 
}

GO2_EXPORT(Go2ProfileArea) Go2ProfileFeature_Area(Go2ProfileFeature feature)
{
    Go2ProfileFeatureClass* obj = zHANDLE_POINTER(feature);
    return obj->area; 
}

/*
 * Go2ProfileLine Class 
 */

GO2_EXPORT(Go2Status) Go2ProfileLine_Construct(Go2ProfileLine* line, Go2System system)
{
    Go2ProfileLine output = zNIL; 
    Go2Status status = GO2_OK; 

    zCHECK(zCalloc(&output, 1, sizeof(Go2ProfileLineClass))); 

    if (!zSUCCESS(status = Go2ProfileLine_Init(output, system)))
    {
        zCHECK(Go2Object_Destroy(output)); 
        return status; 
    }
    
    *line = output; 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileLine_Init(Go2ProfileLine line, Go2System system)
{
    Go2ProfileLineClass* obj = zHANDLE_POINTER(line);
    z32u i; 

    zCHECK(Go2Object_Init(line, GO2_TYPE_PROFILE_LINE)); 

    obj->Release = Go2ProfileLine_VRelease; 
    obj->system = system; 

    for (i = 0; i < zCOUNT(obj->areas); ++i)
    {
        zCHECK(Go2ProfileArea_Construct(&obj->areas[i], system)); 
        obj->areaCount++; 
    }

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileLine_VRelease(Go2ProfileLine line)
{
    Go2ProfileLineClass* obj = zHANDLE_POINTER(line);
    z32u i; 

    for (i = 0; i < zCOUNT(obj->areas); ++i)
    {
        zCHECK(Go2Object_Destroy(obj->areas[i])); 
    }

    zCHECK(Go2Object_VRelease(line)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileLine_Read(Go2ProfileLine line, zXml xml, zXml item)
{
    Go2ProfileLineClass* obj = zHANDLE_POINTER(line);
    zXmlItem areaItem = zNIL; 

    zCHECK(!zIS_NIL(areaItem = zXml_Child(xml, item, "Area")));    
    zCHECK(Go2ProfileArea_Read(obj->areas[0], xml, areaItem));  
    obj->areaCount = 1; 

    if (!zIS_NIL(areaItem = zXml_NextSibling(xml, areaItem)) && 
        (strcmp(zXml_ItemName(xml, areaItem), "Area") == 0))
    {
        zCHECK(Go2ProfileArea_Read(obj->areas[1], xml, areaItem));  
        obj->areaCount++;  
    }

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileLine_Write(Go2ProfileLine line, zXml xml, zXml item)
{
    Go2ProfileLineClass* obj = zHANDLE_POINTER(line);
    zXmlItem areaItem = zNIL; 
    z32u i; 

    for (i = 0; i < obj->areaCount; ++i)
    {
        zCHECK(zXml_AddItem(xml, item, "Area", &areaItem)); 
        zCHECK(Go2ProfileArea_Write(obj->areas[i], xml, areaItem)); 
    }

    return GO2_OK; 
}

GO2_EXPORT(Go2UInt32) Go2ProfileLine_AreaCount(Go2ProfileLine line)
{
    Go2ProfileLineClass* obj = zHANDLE_POINTER(line);
    return obj->areaCount; 
}

GO2_EXPORT(Go2ProfileArea) Go2ProfileLine_AreaAt(Go2ProfileLine line, Go2UInt32 index)
{
    Go2ProfileLineClass* obj = zHANDLE_POINTER(line);
    return obj->areas[index]; 
} 


/*
 * Go2ProfileEdge Class 
 */

GO2_EXPORT(Go2Status) Go2ProfileEdge_Construct(Go2ProfileEdge* edge, Go2System system)
{
    Go2ProfileEdge output = zNIL; 
    Go2Status status = GO2_OK; 

    zCHECK(zCalloc(&output, 1, sizeof(Go2ProfileEdgeClass))); 

    if (!zSUCCESS(status = Go2ProfileEdge_Init(output, system)))
    {
        zCHECK(Go2Object_Destroy(output)); 
        return status; 
    }
    
    *edge = output; 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_Init(Go2ProfileEdge edge, Go2System system)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);

    zCHECK(Go2Object_Init(edge, GO2_TYPE_PROFILE_EDGE)); 

    obj->Release = Go2ProfileEdge_VRelease; 
    obj->system = system; 

    zCHECK(Go2ProfileArea_Construct(&obj->area, system)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_VRelease(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);

    zCHECK(Go2Object_Destroy(obj->area)); 

    zCHECK(Go2Object_VRelease(edge)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_Read(Go2ProfileEdge edge, zXml xml, zXmlItem item)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    zXmlItem areaItem = zNIL; 

    zCHECK(zXml_Child64f(xml, item, "VoidWidthMax", &obj->voidWidthMax)); 
    zCHECK(zXml_Child64f(xml, item, "DepthMin", &obj->depthMin));
    zCHECK(zXml_Child64f(xml, item, "SurfaceWidth", &obj->surfaceWidth)); 
    zCHECK(zXml_Child64f(xml, item, "SurfaceOffset", &obj->surfaceOffset));
    zCHECK(zXml_Child64f(xml, item, "NominalRadius", &obj->nominalRadius));
    zCHECK(zXml_Child64f(xml, item, "EdgeAngle", &obj->edgeAngle));
    zCHECK(zXml_Child32s(xml, item, "EdgeType", (z32s*) &obj->edgeType)); 

    zCHECK(!zIS_NIL(areaItem = zXml_Child(xml, item, "Area"))); 
    zCHECK(Go2ProfileArea_Read(obj->area, xml, areaItem));  

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_Write(Go2ProfileEdge edge, zXml xml, zXmlItem item)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    zXmlItem areaItem = zNIL; 

    zCHECK(zXml_SetChild64f(xml, item, "VoidWidthMax", obj->voidWidthMax)); 
    zCHECK(zXml_SetChild64f(xml, item, "DepthMin", obj->depthMin)); 
    zCHECK(zXml_SetChild64f(xml, item, "SurfaceWidth", obj->surfaceWidth)); 
    zCHECK(zXml_SetChild64f(xml, item, "SurfaceOffset", obj->surfaceOffset)); 
    zCHECK(zXml_SetChild64f(xml, item, "NominalRadius", obj->nominalRadius)); 
    zCHECK(zXml_SetChild64f(xml, item, "EdgeAngle", obj->edgeAngle)); 
    zCHECK(zXml_SetChild32s(xml, item, "EdgeType", obj->edgeType)); 

    zCHECK(zXml_AddItem(xml, item, "Area", &areaItem)); 
    zCHECK(Go2ProfileArea_Write(obj->area, xml, areaItem));  

    return GO2_OK; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_SetType(Go2ProfileEdge edge, Go2ProfileEdgeType type)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge); 

    zCHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->edgeType = type; 
    zCHECK(Go2System_SetModified(obj->system)); 

    return GO2_OK; 
}

GO2_EXPORT(Go2ProfileEdgeType) Go2ProfileEdge_Type(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return obj->edgeType; 
}

GO2_EXPORT(Go2ProfileArea) Go2ProfileEdge_Area(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return obj->area; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_SetVoidWidthMax(Go2ProfileEdge edge, Go2Double width)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);

    zCHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->voidWidthMax = width; 
    zCHECK(Go2System_SetModified(obj->system));  

    return GO2_OK; 
}

GO2_EXPORT(Go2Double) Go2ProfileEdge_VoidWidthMax(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return obj->voidWidthMax; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_SetDepthMin(Go2ProfileEdge edge, Go2Double depth)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);

    zCHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->depthMin = depth; 
    zCHECK(Go2System_SetModified(obj->system));  

    return GO2_OK; 
}

GO2_EXPORT(Go2Double) Go2ProfileEdge_DepthMin(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return obj->depthMin; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_SetSurfaceWidth(Go2ProfileEdge edge, Go2Double width)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);

    zCHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->surfaceWidth = width; 
    zCHECK(Go2System_SetModified(obj->system));  

    return GO2_OK; 
}

GO2_EXPORT(Go2Double) Go2ProfileEdge_SurfaceWidth(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return obj->surfaceWidth; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_SetSurfaceOffset(Go2ProfileEdge edge, Go2Double offset)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);

    zCHECK(Go2System_CheckConfigurable(obj->system)); 
    obj->surfaceOffset = offset; 
    zCHECK(Go2System_SetModified(obj->system));  

    return GO2_OK; 
}

GO2_EXPORT(Go2Double) Go2ProfileEdge_SurfaceOffset(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return obj->surfaceOffset; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_SetNominalRadius(Go2ProfileEdge edge, Go2Double radius)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return Go2System_Set64f(obj->system,  &obj->nominalRadius, radius, -z64F_MAX, z64F_MAX);     
}

GO2_EXPORT(Go2Double) Go2ProfileEdge_NominalRadius(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return obj->nominalRadius; 
}

GO2_EXPORT(Go2Status) Go2ProfileEdge_SetEdgeAngle(Go2ProfileEdge edge, Go2Double angle)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return Go2System_Set64f(obj->system,  &obj->edgeAngle, angle, -z64F_MAX, z64F_MAX);     
}

GO2_EXPORT(Go2Double) Go2ProfileEdge_EdgeAngle(Go2ProfileEdge edge)
{
    Go2ProfileEdgeClass* obj = zHANDLE_POINTER(edge);
    return obj->edgeAngle; 
}

