/**
 * Function insert_library
 * inserts a library into the project and refreshes libraries.
 *
 * @param aProject - project that will be modified
 * @param aLibrary - PART_LIB to add
 * @param aIndex - index in the list at which the library is to be inserted
 *
 * @return true on success, false on failure
 */
static bool insert_library( PROJECT *aProject, PART_LIB *aLibrary, size_t aIndex ) throw( boost::bad_pointer )
{
    wxArrayString libNames;
    wxString libPaths;

    wxString libName = aLibrary->GetName();
    PART_LIBS *libs = dynamic_cast<PART_LIBS*>( aProject->GetElem( PROJECT::ELEM_SCH_PART_LIBS ) );
    if( !libs )
    {
        libs = new PART_LIBS();
        aProject->SetElem( PROJECT::ELEM_SCH_PART_LIBS, libs );
    }

    try
    {
        PART_LIBS::LibNamesAndPaths( aProject, false, &libPaths, &libNames );

        // Make sure the library is not already in the list
        while( libNames.Index( libName ) != wxNOT_FOUND )
            libNames.Remove( libName );

        // Add the library to the list and save
        libNames.Insert( libName, aIndex );
        PART_LIBS::LibNamesAndPaths( aProject, true, &libPaths, &libNames );
    }
    catch( const IO_ERROR& )
    {
        // Could not get or save the current libraries.
        return false;
    }

    // Save the old libraries in case there is a problem after clear(). We'll
    // put them back in.
    boost::ptr_vector<PART_LIB> libsSave;
    libsSave.transfer( libsSave.end(), libs->begin(), libs->end(), *libs );

    aProject->SetElem( PROJECT::ELEM_SCH_PART_LIBS, NULL );

    libs = new PART_LIBS();
    try
    {
        libs->LoadAllLibraries( aProject );
    }
    catch( const PARSE_ERROR& )
    {
        // Some libraries were not found. There's no point in showing the error,
        // because it was already shown. Just don't do anything.
    }
    catch( const IO_ERROR& )
    {
        // Restore the old list
        libs->clear();
        libs->transfer( libs->end(), libsSave.begin(), libsSave.end(), libsSave );
        return false;
    }
    aProject->SetElem( PROJECT::ELEM_SCH_PART_LIBS, libs );

    return true;
}
bool DIALOG_SYMBOL_REMAP::remapSymbolToLibTable( SCH_COMPONENT* aSymbol )
{
    wxCHECK_MSG( aSymbol != NULL, false, "Null pointer passed to remapSymbolToLibTable." );
    wxCHECK_MSG( aSymbol->GetLibId().GetLibNickname().empty(), false,
                 "Cannot remap symbol that is already mapped." );
    wxCHECK_MSG( !aSymbol->GetLibId().GetLibItemName().empty(), false,
                 "The symbol LIB_ID name is empty." );

    PART_LIBS* libs = Prj().SchLibs();

    for( PART_LIBS_BASE::iterator it = libs->begin(); it != libs->end(); ++it )
    {
        // Ignore the cache library.
        if( it->IsCache() )
            continue;

        LIB_ALIAS* alias = it->FindAlias( aSymbol->GetLibId().GetLibItemName().wx_str() );

        // Found in the same library as the old look up method assuming the user didn't
        // change the libraries or library ordering since the last time the schematic was
        // loaded.
        if( alias )
        {
            // Find the same library in the symbol library table using the full path and file name.
            wxString libFileName = it->GetFullFileName();

            const LIB_TABLE_ROW* row = Prj().SchSymbolLibTable()->FindRowByURI( libFileName );

            if( row )
            {
                LIB_ID id = aSymbol->GetLibId();

                id.SetLibNickname( row->GetNickName() );

                // Don't resolve symbol library links now.
                aSymbol->SetLibId( id, nullptr, nullptr );
                return true;
            }
        }
    }

    return false;
}
size_t DIALOG_SYMBOL_REMAP::getLibsNotInGlobalSymbolLibTable( std::vector< PART_LIB* >& aLibs )
{
    PART_LIBS* libs = Prj().SchLibs();

    for( PART_LIBS_BASE::iterator it = libs->begin(); it != libs->end(); ++it )
    {
        // Ignore the cache library.
        if( it->IsCache() )
            continue;

        // Check for the obvious library name.
        wxString libFileName = it->GetFullFileName();

        if( !SYMBOL_LIB_TABLE::GetGlobalLibTable().FindRowByURI( libFileName ) )
            aLibs.push_back( &(*it) );
    }

    return aLibs.size();
}