/*--------------------------------------------------------------------------------------+
|  $Copyright: (c) 2020 Bentley Systems, Incorporated. All rights reserved. $
+--------------------------------------------------------------------------------------*/
#include "_ustation.h"

#include "BeXMLNode.h"
#include "BARDEF.H"
#include "SelectionRebar.h"

#include "dialogs.h"
#include <Mstn\MdlApi\msdialog.fdf>

using namespace RebarSpace;

class RebarSDK_GenericSelectionRebar : public SelectionRebar
{
    BE_DATA_REFER(BeXMLRoot, XMLFile)

    void MeasureRebarCurve(CurveVectorCR curve, double &totlength) const
    {
        DSegment3dCP seg = nullptr;
        DEllipse3dCP arc = nullptr;
        double length = 0.0;
        for (ICurvePrimitivePtr prim : curve)
        {
            switch (prim->GetCurvePrimitiveType())
            {
            case ICurvePrimitive::CurvePrimitiveType::CURVE_PRIMITIVE_TYPE_CurveVector:
            {
                CurveVectorCR child = *prim->GetChildCurveVectorCP();
                MeasureRebarCurve(child, totlength);
            }
            break;
            case ICurvePrimitive::CURVE_PRIMITIVE_TYPE_Line:
            {
                seg = prim->GetLineCP();
                if (seg != nullptr)
                {
                    CPoint3D pt1 = seg->point[0];
                    CPoint3D pt2 = seg->point[1];
                    length = pt1.Distance(pt2);
                    totlength += length;
                }
            }
            break;
            case ICurvePrimitive::CURVE_PRIMITIVE_TYPE_Arc:
            {
                arc = prim->GetArcCP();
                if (arc != nullptr)
                {
                    length = arc->ArcLength();
                    totlength += length;
                }
            }
            break;
            }
        }
    }

    // on the mouse LEFT_BUTTON
    virtual StatusInt DataPoint(DPoint3dCP point, int view) override
    {
        DgnModelRefP modelRef = ACTIVEMODEL;
        ULong filepos = mdlLocate_findElement(point, view, FALSE, ComponentMode::None, FALSE);
        ElementRefP elemRef = mdlModelRef_getElementRef(modelRef, filepos);
        ElementHandle eh(elemRef);

        double totlength = 0.0;
        if (RebarElement::IsRebarElement(eh))
        {
            RebarElementP rep = RebarElement::Fetch(eh);
            if (rep != nullptr)
            {
                StatusInt AddWorked = PopRebarElements().Add(rep);

                if (SUCCESS == AddWorked)
                {
                    //Output rep ElementId and diameter to ASCII file
                    Process(rep);
                }

                RebarSetCP rebar_setP = rep->RelationRebarSetMaster(0);
                if (rebar_setP != nullptr)
                {
                    ssize_t num_qty = rebar_setP->RelationCountRebarElementMaster();
                }

                CurveVectorPtr curve = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Open);
                rep->GetCurveVector(*curve, modelRef);
                MeasureRebarCurve(*curve, totlength);
            }
        }
        return GetRebarElements().GetSize() > 0 ? SUCCESS : ERROR;
    }

    // on the mouse RIGHT_BTTON
    virtual StatusInt DataReset() override
    {
        GetXMLFile().WriteFile(L"RebarSDKTest.XML");
        SelectionRebar::EndSelectElement(true);
        return SUCCESS;
    }

    virtual StatusInt Process(RebarElementP rep) override
    {
        const RebarShapeData *shape = rep != nullptr ? rep->GetShapeData(ACTIVEMODEL) : nullptr;
        if (shape != nullptr)
        {
            BeXMLNode *node = PopXMLFile().AddXMLNode(L"Data");
            node->AddXMLData(L"ElementID", (int)rep->GetElementId());
            node->AddXMLData(L"Size", (LPCTSTR)shape->GetSizeKey());
            node->AddXMLData(L"Barmark", (LPCTSTR)shape->GetBarmark());
            node->AddXMLData(L"Posnum", (LPCTSTR)shape->GetPosnum());
            node->AddXMLData(L"Coating", (LPCTSTR)shape->GetCoating());
            node->AddXMLData(L"Surface", (LPCTSTR)shape->GetSurface());
            node->AddXMLData(L"Material", shape->GetMaterial());
            node->AddXMLData(L"Length", shape->GetLength());
            node->AddXMLData(L"NominalLength", shape->GetNominalLength());
            node->AddXMLData(L"Weight", shape->GetWeight());
            node->AddXMLData(L"IsStirrup", shape->GetIsStirrup());
            node->AddXMLData(L"ShapeCode", (LPCTSTR)shape->GetShapeCode());

            BeXMLNode *dimNode = node->AddXMLNode(L"Dimensions");
            dimNode->AddXMLData(L"Size", (int)shape->GetDimensions().size());
            for (int i = 0; i < shape->GetDimensions().size(); ++i)
            {
                const RebarDimData &rebar_dim = shape->GetDimensions()[i];
                bool isHidden = (int)rebar_dim.GetDimType() & RebarDimData::kHidden;
                if (!isHidden)
                {
                    dimNode->AddXMLData(L"Name", (LPCTSTR)rebar_dim.GetDimName());
                    dimNode->AddXMLData(L"Length", rebar_dim.GetDimLength());
                }
            }
        }
        return SUCCESS;
    }

    virtual void Prompt()
    {
        mdlOutput_prompt(L"Rebar SDK: Select Rebar <Reset to end selection>:");
    }

  public:
    RebarSDK_GenericSelectionRebar()
    {
        m_XMLFile.SetName(L"RebarSDK_Generic");
    }
};

////////////////////////////////////////////////////////////////////////////////////////

class RebarSDK_ARMA_Data
{
    BE_DATA_VALUE(int, QTY)

    BE_DATA_REFER(BrString, ElementName)
    BE_DATA_REFER(BrString, ElementDescription)
    BE_DATA_REFER(BrString, ElementAbreviation)
    BE_DATA_REFER(BrString, ElementCount)

    BE_DATA_REFER(BrString, Barmark)
    BE_DATA_REFER(BrString, TypeofWork)

    BE_DATA_REFER(BrString, Grade)
    BE_DATA_REFER(BrString, Dia)

    BE_DATA_REFER(BrString, SizeKey)
    BE_DATA_REFER(BrString, PIN)
    BE_DATA_REFER(BrString, ShapeCode)
    BE_DATA_REFER(BrString, VarySet)

    BE_DATA_ARRAY(BrString, Dim, 26)

  public:
    RebarSDK_ARMA_Data()
        : m_QTY(0)
    {
    }

    int Compare(const RebarSDK_ARMA_Data &other, int mode = 0, int flag = 0) const
    {
        int ret = GetElementName().Compare(other.GetElementName());
        if (0 == ret)
            ret = GetBarmark().Compare(other.GetBarmark());
        return ret;
    }
};

class RebarSDK_ARMA_List : public BeFastArray<RebarSDK_ARMA_Data>
{
  public:
    RebarSDK_ARMA_List()
    {
    }
};

class RebarSDK_ARMASelectionRebar : public SelectionRebar
{
    BE_DATA_REFER(BeFileName, ARMAFileName)
    BE_DATA_REFER(RebarSDK_ARMA_List, ArmaList)

    BE_DATA_REFER(BrString, Option)
    BE_DATA_REFER(BrString, DrawingNumber)
    BE_DATA_REFER(BrString, DrawingTitle)
    BE_DATA_REFER(BrString, ContractFile)
    BE_DATA_REFER(BrString, ContractNumber)
    BE_DATA_REFER(BrString, DeliveryDate)

  public:
    // on the mouse RIGHT_BTTON
    RebarSDK_ARMASelectionRebar()
    {
    }
    virtual StatusInt DataReset() override
    {
        // TODO - write the structure list to the file

        SelectionRebar::EndSelectElement(true);
        return SUCCESS;
    }

	
    virtual StatusInt Process(RebarElementP rep) override
    {
        DgnModelRefP modelRef = ACTIVEMODEL;
        const RebarShapeData *shape = rep != nullptr ? rep->GetShapeData(modelRef) : nullptr;
        if (shape != nullptr)
        {
            BrString barmark = shape->GetBarmark();
            RebarSDK_ARMA_Data arma_data;
            
            BeConcreteData conc_data;
            int rebar_cage_type = 0;
            ElementId concreteId = rep->GetConcreteOwner(modelRef, rebar_cage_type);		
            rep->GetConcreteData(concreteId, modelRef, conc_data);			

            BrString ElementName = conc_data.GetElementName();
            arma_data.SetElementName(ElementName);
            arma_data.SetBarmark(barmark);
            int index = (int)GetArmaList().FindIndex(&arma_data);
            if (index == -1)
            {
                RebarSDK_ARMA_Data *arma_dataP = new RebarSDK_ARMA_Data;
                BrString ElementDescription = conc_data.GetDescription();
                BrString abbrev = conc_data.GetAbreviation();
                int elementCount = conc_data.GetCount();

                BrString Barmark = barmark;

                BrString TypeofWork = L"STR";
                WString value;

                const RebarShape *sh = rep->GetRebarShape(modelRef);
                if (sh != nullptr)
                {
                    RebarCurve curve;
                    if (sh->GetRebarCurve(curve))
                    {
                        const RebarVertices &vertices = curve.GetVertices();
                        intptr_t numVertices = vertices.GetSize();
                        if (numVertices > 2)
                            TypeofWork = L"CB";
                    }
                }

                double uorfactor = modelRef->GetModelInfoCP()->GetUorPerStorage();
                BE_INIT_SETTING
                BE_SET_CURRENT_MODELREF(modelRef)

                if (0.0 == uorfactor)
                    uorfactor = 1.0;
                BrString SizeKey = shape->GetSizeKey();
                double diameter = RebarCode::GetBarDiameter(SizeKey, modelRef);    // get the diameter from the RebarCode based on SizeKey not the internal value which is always in mm
                BrString Dia;
                Ben::Units currUnits = GetModelRefUnits(modelRef);
                ToDlgStr(Dia, diameter, currUnits, 0);

                BrString Grade = shape->GetGrade();

                double pin = RebarCode::GetPinRadius(SizeKey, modelRef, shape->GetIsStirrup()) - diameter / 2.0;
                pin = pin * 2.0;
                BrString PIN; // pin is diameter
                ToDlgStr(PIN, pin, currUnits, 0);

                BrString ShapeCode = shape->GetShapeCode();
                const RebarDimDataArray &dimensions = shape->GetDimensions();
                size_t size = dimensions.size();
                // remember that dimensions in shape are in mm calculated by aSa
                double mm_to_uor = modelRef->GetModelInfoCP()->GetUorPerMeter() / 1000.0;
                for (int j = 0; j < 26; j++)
                {
                    if (size > 0)
                    {
                        for (int i = 0; i < size; i++)
                        {
                            const RebarDimData &rebar_dim = dimensions[i];
                            bool isHidden = (int)rebar_dim.GetDimType() & RebarDimData::kHidden;
                            if (isHidden)
                                continue;

                            BrString CIndex = rebar_dim.GetDimName();
                            int CNumCap = j + 65;
                            int CNum = j + 97;
                            if (CIndex[0] == CNum || CIndex[0] == CNumCap) // what ever it is capital 
                            {
                                double len = rebar_dim.GetDimLength() * mm_to_uor;
                                if (len > 0.0)
                                {
                                    BrString dimLength;
                                    ToDlgStr(dimLength, len, currUnits, 0);
                                    arma_dataP->SetDim(j, dimLength);
                                }
                                break;
                            }
                        }
                    }
                    else if (11 == j)
                    {
                        double len = shape->GetLength() * mm_to_uor;
                        BrString dimLength;
                        ToDlgStr(dimLength, len, currUnits, 0);
                        arma_dataP->SetDim(j, dimLength);
                    }
                }
                bool isVarySet = shape->GetVarySetId() > 0;
                //arma_dataP->SetDrawingNumber(DrawingNumber);
                //arma_dataP->SetDrawingTitle(DrawingTitle);
                arma_dataP->SetElementName(ElementName);
                arma_dataP->SetElementDescription(ElementDescription);
                arma_dataP->SetElementAbreviation(abbrev);
                arma_dataP->SetElementCount(elementCount);      // number of concrete elements

                arma_dataP->SetBarmark(barmark);
                arma_dataP->SetQTY(1);              // number of bars per barmark within one element
                arma_dataP->SetGrade(Grade);
                arma_dataP->SetDia(Dia);

                arma_dataP->SetShapeCode(ShapeCode);
                arma_dataP->SetTypeofWork(TypeofWork);
                arma_dataP->SetSizeKey(SizeKey);
                arma_dataP->SetPIN(PIN);
                arma_dataP->SetVarySet(isVarySet ? L"1" : L"0");
                // todo all the heading
                PopArmaList().Add(arma_dataP);
            }
            else
            {
                int &qty = PopArmaList().GetAt(index)->PopQTY();
                qty++;
            }
        }
        return SUCCESS;
    }

    // get the general information
    StatusInt ReadDialog()
    {
        StatusInt ret = ERROR;
        BeXMLRoot dialog_xml_node;

        TCHAR xml_fileName[256];
        if (mdlModelRef_getFileName(ACTIVEMODEL, xml_fileName, COUNT_OF(xml_fileName)) == SUCCESS)
        {
            _tcscat(xml_fileName, L".xml");
            if (dialog_xml_node.ReadFile(xml_fileName, false))
            {
                dialog_xml_node.FindValue(PopOption(), L"Option");
                dialog_xml_node.FindValue(PopDrawingNumber(), L"DrawingNumber");
                dialog_xml_node.FindValue(PopDrawingTitle(), L"DrawingTitle");
                dialog_xml_node.FindValue(PopContractFile(), L"ContractFile");
                dialog_xml_node.FindValue(PopContractNumber(), L"ContractNumber");
                dialog_xml_node.FindValue(PopDeliveryDate(), L"DeliveryDate");
                ret = SUCCESS;
            }
        }
        return ret;
    }

    StatusInt WriteDialog()
    {
        StatusInt ret = ERROR;
        BeXMLRoot general_info_xml_node;

        TCHAR xml_fileName[256];
        if (mdlModelRef_getFileName(ACTIVEMODEL, xml_fileName, COUNT_OF(xml_fileName)) == SUCCESS)
        {
            _tcscat(xml_fileName, L".xml");
            general_info_xml_node.SetName(L"ARMA");
            general_info_xml_node.AddXMLData(L"Option", GetOption());
            general_info_xml_node.AddXMLData(L"DrawingNumber", GetDrawingNumber());
            general_info_xml_node.AddXMLData(L"DrawingTitle", GetDrawingTitle());
            general_info_xml_node.AddXMLData(L"ContractFile", GetContractFile());
            general_info_xml_node.AddXMLData(L"ContractNumber", GetContractNumber());
            general_info_xml_node.AddXMLData(L"DeliveryDate", GetDeliveryDate());

            if (general_info_xml_node.WriteFile(xml_fileName))
            {
                ret = SUCCESS;
            }
        }
        return ret;
    }
};


static RebarSDK_ARMASelectionRebar * s_dialogDataP = nullptr;

/*=================================================================================**//**
* @bsiclass  
+===============+===============+===============+===============+===============+======*/
class ARMASettingsDialog
{

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                                    
+---------------+---------------+---------------+---------------+---------------+------*/
private:
static void DialogHook (DialogMessage* dmP)
    {
    dmP->msgUnderstood = true;

    RebarSDK_ARMASelectionRebar *arma_select = s_dialogDataP;

    switch (dmP->messageType)
        {
        case DIALOG_MESSAGE_INIT:
            {
            DialogItem* diP = mdlDialog_itemGetByTypeAndId (dmP->db, RTYPE_OptionButton, OPTIONBUTTONID_ARMAOption, 0);
            if (diP)
                {
                MSValueDescr value(0);
                mdlDialog_itemSetValue (NULL, value, dmP->db, diP->itemIndex);

                arma_select->ReadDialog();
                bool changedValue = false;
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_OptionButton, OPTIONBUTTONID_ARMAOption, 0)))
                {
                    value.SetWChar(arma_select->GetOption());
                    mdlDialog_itemSetValue(&changedValue, value, dmP->db, diP->itemIndex);
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_DrawingNumber, 0)))
                {
                    value.SetWChar(arma_select->GetDrawingNumber());
                    mdlDialog_itemSetValue(&changedValue, value, dmP->db, diP->itemIndex);
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_DrawingTitle, 0)))
                {
                    value.SetWChar(arma_select->GetDrawingTitle());
                    mdlDialog_itemSetValue(&changedValue, value, dmP->db, diP->itemIndex);
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_ContractFile, 0)))
                {
                    value.SetWChar(arma_select->GetContractFile());
                    mdlDialog_itemSetValue(&changedValue, value, dmP->db, diP->itemIndex);
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_ContractNumber, 0)))
                {
                    value.SetWChar(arma_select->GetContractNumber());
                    mdlDialog_itemSetValue(&changedValue, value, dmP->db, diP->itemIndex);
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_DeliveryDate, 0)))
                {
                    value.SetWChar(arma_select->GetDeliveryDate());
                    mdlDialog_itemSetValue(&changedValue, value, dmP->db, diP->itemIndex);
                }
            }
            break;
        }

        case DIALOG_MESSAGE_ACTIONBUTTON:
        {
            if (ACTIONBUTTON_OK == dmP->u.actionButton.actionType)
            {
                DialogItem *diP;
                MSValueDescr value;

                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_OptionButton, OPTIONBUTTONID_ARMAOption, 0)))
                {
                    mdlDialog_itemGetValue(value, dmP->db, diP->itemIndex);
                    arma_select->SetOption(0 == value.GetULong() ? L"ARM" : L"CSV");
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_DrawingNumber, 0)))
                {
                    mdlDialog_itemGetValue(value, dmP->db, diP->itemIndex);
                    arma_select->SetDrawingNumber(value.GetWCharCP());
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_DrawingTitle, 0)))
                {
                    mdlDialog_itemGetValue(value, dmP->db, diP->itemIndex);
                    arma_select->SetDrawingTitle(value.GetWCharCP());
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_ContractFile, 0)))
                {
                    mdlDialog_itemGetValue(value, dmP->db, diP->itemIndex);
                    arma_select->SetContractFile(value.GetWCharCP());
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_ContractNumber, 0)))
                {
                    mdlDialog_itemGetValue(value, dmP->db, diP->itemIndex);
                    arma_select->SetContractNumber(value.GetWCharCP());
                }
                if (NULL != (diP = mdlDialog_itemGetByTypeAndId(dmP->db, RTYPE_Text, TEXTID_DeliveryDate, 0)))
                {
                    mdlDialog_itemGetValue(value, dmP->db, diP->itemIndex);
                    arma_select->SetDeliveryDate(value.GetWCharCP());
                }
                arma_select->WriteDialog();
            }
            break;
        }

        default:
            dmP->msgUnderstood = false;
            break;
        }
    }

  public:
    /*---------------------------------------------------------------------------------**/ /**
    * @bsimethod                                                    
    +---------------+---------------+---------------+---------------+---------------+------*/
    static BentleyStatus OpenModel(RebarSDK_ARMASelectionRebar *arma_select)
    {
        int lastAction = PUSHBUTTONID_Cancel;
        s_dialogDataP = arma_select;
        StatusInt status = mdlDialog_openModal(&lastAction, NULL, DIALOGID_ARMASettings);
        s_dialogDataP = NULL;

        return SUCCESS == status && ACTIONBUTTON_OK == lastAction ? SUCCESS : ERROR;
    }

    /*---------------------------------------------------------------------------------**/ /**
    * @bsimethod                                                    
    +---------------+---------------+---------------+---------------+---------------+------*/
    static void Initialize()
    {
        static bool hooks_published = false;

        if (!hooks_published)
        {
            static DialogHookInfo uHooks[] =
                {
                    {HOOKDIALOGID_ARMASettings, (PFDialogHook)DialogHook},
                };

            mdlDialog_hookPublish(sizeof(uHooks) / sizeof(DialogHookInfo), uHooks);
            hooks_published = true;
        }
    }
}; // ARMASettingsDialog


extern "C" StatusInt rebar_displayFeatureBetaMessage();


/*Public*/ /*cmdName*/ void RebarSDK_ARMA(WCharCP unparsedP)
/*cmdNumber CMD_REBAR_TEST*/
{
    rebar_displayFeatureBetaMessage();
    ARMASettingsDialog::Initialize();

    BeSharpPtr<RebarSDK_ARMASelectionRebar> arma_select;

    if (SUCCESS != ARMASettingsDialog::OpenModel(arma_select()))
        return;

    BeFileName fileName;
    BrString extendName = BrString(L"*.ARM");
    BrString option = BrString(L"ARM");
    if (arma_select->GetOption() == L"CSV")
    {
        extendName = BrString(L"*.CSV");
        option = BrString(L"CSV");
    }

    if (mdlDialog_fileCreate(fileName, NULL, 0, L"", extendName, NULL, L"ARMA File") == SUCCESS)
    {
        CStdioFile ArmaFile;
        CFileException ex;
        try
        {
            if (!ArmaFile.Open(fileName, CFile::modeWrite | CFile::modeCreate | CFile::typeText, &ex))
            {
                return;
            }

            arma_select->SetARMAFileName(fileName);

            if (arma_select->GetOption() == L"ARM")
            {
                BrString ContractFile = arma_select->GetContractFile();
                BrString ContractNumber = arma_select->GetContractNumber();
                BrString ContractLine = L"C,";
                ContractLine = ContractLine + ContractFile.Get() + L"," + ContractNumber.Get() + L"\n";
                ArmaFile.WriteString(ContractLine);

                arma_select->ProcessElements(); // get data related to selected bars sorted by barmark
                //SelectionRebar::SelectElement(*arma_select);

                ArmaFile.SeekToEnd();

                BrString elementline = L"";
                int count = (int)arma_select->GetArmaList().GetSize();
                BrString elementName = L"";
                for (int i = 0; i < count; i++)
                {
                    BrString elementNameString = arma_select->GetArmaList().GetAt(i)->GetElementName();
                    if (elementNameString != elementName || i == 0)
                    {
                        elementline = L"E,";
                        elementline = elementline + elementNameString + L",";
                        elementline = elementline + arma_select->GetArmaList().GetAt(i)->GetElementCount() + L",";
                        elementline = elementline + arma_select->GetDeliveryDate() + L",";
                        elementline = elementline + arma_select->GetArmaList().GetAt(i)->GetElementDescription();
                        elementline = elementline + L"\n";

                        ArmaFile.WriteString(elementline);
                        elementName = elementNameString;
                    }

                    BrString lineItem = L"L,";
                    BrString qty(arma_select->GetArmaList().GetAt(i)->GetQTY());
                    lineItem = lineItem + arma_select->GetArmaList().GetAt(i)->GetBarmark() + L",";
                    lineItem = lineItem + arma_select->GetArmaList().GetAt(i)->GetTypeofWork() + L",";
                    lineItem = lineItem + qty + L",";
                    lineItem = lineItem + arma_select->GetArmaList().GetAt(i)->GetGrade() + L",";
                    lineItem = lineItem + arma_select->GetArmaList().GetAt(i)->GetDia() + L",";
                    lineItem = lineItem + arma_select->GetArmaList().GetAt(i)->GetShapeCode();
                    //Dimension values
                    bool Bfirst = true;
                    for (int j = 0; j < 26; j++)
                    {
                        BrString cNum = arma_select->GetArmaList().GetAt(i)->GetDim()[j];
                        if (!cNum.IsEmpty())
                        {
                            WCHAR dimLetter[2] = L"";
                            dimLetter[0] = j + 65;
                            BrString CName = dimLetter;
                            if (Bfirst)
                            {
                                lineItem = lineItem + L"," + CName + L"=" + cNum;
                                Bfirst = false;
                            }
                            else
                            {
                                lineItem = lineItem + L";" + CName + L"=" + cNum;
                            }
                        }
                    }

                    lineItem = lineItem + L"," + arma_select->GetArmaList().GetAt(i)->GetPIN();

                    //Comment
                    lineItem = lineItem + L",";

                    //1 = signifies a vary set, 0 = individual bar.
                    lineItem = lineItem + L"," + arma_select->GetArmaList().GetAt(i)->GetVarySet();

                    lineItem = lineItem + L"\n";
                    ArmaFile.WriteString(lineItem);
                }
            }
            else
            {
                // option2.csv
                ArmaFile.WriteString(L",Drawing Number,Drawing Title,Element Name,Delivery Date,barmark,Type of Work,Grade\\Dia,QTY,SHAPE CODE,PIN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,\n");

                arma_select->ProcessElements(); // get data related to selected bars sorted by barmark
                //SelectionRebar::SelectElement(*arma_select);

                ArmaFile.SeekToEnd();

                int count = (int)arma_select->GetArmaList().GetSize();
                for (int i = 0; i < count; i++)
                {
                    int count = _wtoi(arma_select->GetArmaList().GetAt(i)->GetElementCount());
                    count *= arma_select->GetArmaList().GetAt(i)->GetQTY();
                    BrString qty(count);

                    BrString string = L",";
                    string = string + arma_select->GetDrawingNumber() + L",";
                    string = string + arma_select->GetDrawingTitle() + L",";
                    string = string + arma_select->GetArmaList().GetAt(i)->GetElementName() + L",";
                    string = string + arma_select->GetDeliveryDate() + L",";
                    string = string + arma_select->GetArmaList().GetAt(i)->GetBarmark() + L",";
                    string = string + arma_select->GetArmaList().GetAt(i)->GetTypeofWork() + L",";

                    string = string + arma_select->GetArmaList().GetAt(i)->GetGrade() + L"";
                    string = string + arma_select->GetArmaList().GetAt(i)->GetDia() + L",";

                    string = string + qty + L",";
                    string = string + arma_select->GetArmaList().GetAt(i)->GetShapeCode() + L",";
                    string = string + arma_select->GetArmaList().GetAt(i)->GetPIN() + L",";
                    for (int j = 0; j < 26; j++)
                    {
                        BrString CNum = arma_select->GetArmaList().GetAt(i)->GetDim()[j];
                        string = string + CNum.Get() + L",";
                    }
                    string = string + L"\n";
                    ArmaFile.WriteString(string);
                }
            }
            ArmaFile.Flush();
            ArmaFile.Close();
        }
        catch (CFileException *e)
        {
            MessageBox(NULL, L"Unable to save", L"Rebar ARMA", MB_OK);
            e->Delete();
        }
    }
    //SelectionRebar::EndSelectElement(false);
}

void GenericXMLRebarSelection()
{
    RebarSDK_GenericSelectionRebar *xml_select = new RebarSDK_GenericSelectionRebar;

    xml_select->ProcessElements();
    SelectionRebar::SelectElement(*xml_select);
}
