/*!
  \brief Load geometry (linestring HP/DPM layer)

  \return number of invalid features
*/
int VFKDataBlockSQLite::LoadGeometryLineStringHP()
{
    int nInvalid = 0;
    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;

    VFKDataBlockSQLite *poDataBlockLines =
        (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SBP");
    if (NULL == poDataBlockLines) {
        CPLError(CE_Failure, CPLE_FileIO,
                 "Data block %s not found.", m_pszName);
        return nInvalid;
    }

    poDataBlockLines->LoadGeometry();

    if (LoadGeometryFromDB()) /* try to load geometry from DB */
        return 0;

    CPLString osColumn;
    osColumn.Printf("%s_ID", m_pszName);
    const char *vrColumn[2] = {
        osColumn.c_str(),
        "PORADOVE_CISLO_BODU"
    };

    GUIntBig vrValue[2] = { 0, 1 }; // Reduce to first segment.

    CPLString osSQL;
    osSQL.Printf("SELECT ID,%s,rowid FROM %s", FID_COLUMN, m_pszName);
    /* TODO: handle points in DPM */
    if (EQUAL(m_pszName, "DPM"))
        osSQL += " WHERE SOURADNICE_X IS NULL";
    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());

    if (poReader->IsSpatial())
        poReader->ExecuteSQL("BEGIN");

    int nGeometries = 0;

    while( poReader->ExecuteSQL(hStmt) == OGRERR_NONE )
    {
        /* read values */
        vrValue[0] = sqlite3_column_int64(hStmt, 0);
        const long iFID = static_cast<long>(sqlite3_column_int64(hStmt, 1));
        const int rowId = sqlite3_column_int(hStmt, 2);

        VFKFeatureSQLite *poFeature =
            (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
        CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);

        VFKFeatureSQLite *poLine =
            poDataBlockLines->GetFeature(vrColumn, vrValue, 2, TRUE);

        OGRGeometry *poOgrGeometry = NULL;
        if( !poLine )
        {
            poOgrGeometry = NULL;
        }
        else
        {
            poOgrGeometry = poLine->GetGeometry();
        }
        if (!poOgrGeometry || !poFeature->SetGeometry(poOgrGeometry)) {
            CPLDebug("OGR-VFK", "VFKDataBlockSQLite::LoadGeometryLineStringHP(): name=%s fid=%ld "
                     "id=" CPL_FRMT_GUIB " -> %s geometry", m_pszName, iFID, vrValue[0],
                     poOgrGeometry ? "invalid" : "empty");
            nInvalid++;
            continue;
        }

        /* store also geometry in DB */
        if (poReader->IsSpatial() &&
            SaveGeometryToDB(poOgrGeometry, rowId) != OGRERR_FAILURE &&
            poOgrGeometry)
            nGeometries++;
    }

    /* update number of geometries in VFK_DB_TABLE table */
    UpdateVfkBlocks(nGeometries);

    if (poReader->IsSpatial())
        poReader->ExecuteSQL("COMMIT");

    return nInvalid;
}
/*!
  \brief Load geometry (linestring SBP layer)

  \return number of invalid features
*/
int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
{
    int nInvalid = 0;

    VFKDataBlockSQLite *poDataBlockPoints =
        (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SOBR");
    if (NULL == poDataBlockPoints) {
        CPLError(CE_Failure, CPLE_FileIO,
                 "Data block %s not found.\n", m_pszName);
        return nInvalid;
    }

    int nGeometries = 0;
    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;

    poDataBlockPoints->LoadGeometry();

    if (LoadGeometryFromDB()) /* try to load geometry from DB */
        return 0;

    CPLString osSQL;
    osSQL.Printf("UPDATE %s SET %s = -1", m_pszName, FID_COLUMN);
    poReader->ExecuteSQL(osSQL.c_str());
    bool bValid = true;
    int iIdx = 0;

    VFKFeatureSQLite *poLine = NULL;

    for( int i = 0; i < 2; i++ )
    {
        /* first collect linestrings related to HP, OB or DPM
           then collect rest of linestrings */
        if( i == 0 )
            osSQL.Printf("SELECT BP_ID,PORADOVE_CISLO_BODU,PARAMETRY_SPOJENI,_rowid_ FROM '%s' WHERE "
                         "HP_ID IS NOT NULL OR OB_ID IS NOT NULL OR DPM_ID IS NOT NULL "
                         "ORDER BY HP_ID,OB_ID,DPM_ID,PORADOVE_CISLO_BODU", m_pszName);
        else
            osSQL.Printf("SELECT BP_ID,PORADOVE_CISLO_BODU,PARAMETRY_SPOJENI,_rowid_ FROM '%s' WHERE "
                         "OB_ID IS NULL AND HP_ID IS NULL AND DPM_ID IS NULL "
                         "ORDER BY ID,PORADOVE_CISLO_BODU", m_pszName);

        sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());

        if (poReader->IsSpatial())
            poReader->ExecuteSQL("BEGIN");

        std::vector<int> rowIdFeat;
        CPLString szFType;
        OGRLineString oOGRLine;

        while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
            // read values
            const GUIntBig id = sqlite3_column_int64(hStmt, 0);
            const GUIntBig ipcb  = sqlite3_column_int64(hStmt, 1);
            szFType = (char *) sqlite3_column_text(hStmt, 2);
            int rowId = sqlite3_column_int(hStmt, 3);

            if (ipcb == 1) {
                VFKFeatureSQLite *poFeature =
                    (VFKFeatureSQLite *) GetFeatureByIndex(iIdx);
                if( poFeature == NULL )
                {
                    CPLError(CE_Failure, CPLE_AppDefined,
                             "Cannot retrieve feature %d", iIdx);
                    break;
                }
                poFeature->SetRowId(rowId);

                /* set geometry & reset */
                CPLString szFTypeLine;
                if( poLine &&
                    !SetGeometryLineString(
                        poLine, &oOGRLine,
                        bValid, szFTypeLine, rowIdFeat, nGeometries) )
                {
                    nInvalid++;
                }

                bValid = true;
                poLine = poFeature;
                szFTypeLine = szFType;
                iIdx++;
            }

            VFKFeatureSQLite *poPoint =
                (VFKFeatureSQLite *) poDataBlockPoints->GetFeature("ID", id);
            if( poPoint )
            {
                OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
                if (pt) {
                    oOGRLine.addPoint(pt);
                }
                else
                {
                    CPLDebug("OGR-VFK",
                             "Geometry (point ID = " CPL_FRMT_GUIB ") not valid", id);
                    bValid = false;
                }
            }
            else
            {
                CPLDebug("OGR-VFK",
                         "Point ID = " CPL_FRMT_GUIB " not found (rowid = %d)",
                         id, rowId);
                bValid = false;
            }

            /* add vertex to the linestring */
            rowIdFeat.push_back(rowId);
        }

        /* add last line */
        if( poLine &&
            !SetGeometryLineString(
                poLine, &oOGRLine,
                bValid, szFType.c_str(), rowIdFeat, nGeometries) )
        {
            nInvalid++;
        }
        poLine = NULL;

        if (poReader->IsSpatial())
            poReader->ExecuteSQL("COMMIT");
    }

    /* update number of geometries in VFK_DB_TABLE table */
    UpdateVfkBlocks(nGeometries);

    return nInvalid;
}