/********************************************************/
/* Effacements : Routines de sauvegarde et d'effacement */
/********************************************************/

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "confirm.h"

#include "pcbnew.h"


/* Routines externes : */

/* Routines Locales */

/********************************************/
void WinEDA_BasePcbFrame::UnDeleteItem( wxDC* DC )
/********************************************/

/* Restitution d'un element (MODULE ou TRACK ) Efface
 */
{
    BOARD_ITEM*     item;
    int             net_code = 0;

    if( !g_UnDeleteStackPtr )
        return;

    g_UnDeleteStackPtr--;
    item = g_UnDeleteStack[g_UnDeleteStackPtr];
    if( item == NULL )
        return;                     // Ne devrait pas se produire

    // we decremented the stack pointer, so the stack no longer
    // owns "item".  We do here, so we have to delete item if its
    // not going back into the board, see default case below.
    g_UnDeleteStack[g_UnDeleteStackPtr] = NULL;


    switch( item->Type() )
    {
    case TYPE_VIA:
    case TYPE_TRACK:
        TRACK* track;
        track = (TRACK*) item;

        D(printf("%s: track %p status=\"%s\"\n", __func__, track,
                 CONV_TO_UTF8( TRACK::ShowState( track->GetState(-1)) )
                 );)

        track->SetState( DELETED, OFF );
        DrawPanel->PostDirtyRect( track->GetBoundingBox() );
        m_Pcb->Add( track );

        net_code = track->GetNet();

#if !defined(GERBVIEW)
        test_1_net_connexion( DC, net_code );
#endif

        m_Pcb->DisplayInfo( this );
        break;

    case TYPE_BOARD_ITEM_LIST:
        BOARD_ITEM_LIST*  list;
        list = (BOARD_ITEM_LIST*) item;
        while( list->GetCount() )
        {
            TRACK* t = (TRACK*) list->Remove( 0 );
            wxASSERT( t->Type()==TYPE_TRACK || t->Type()==TYPE_VIA );
            t->SetState( DELETED, OFF );
            DrawPanel->PostDirtyRect( t->GetBoundingBox() );
            m_Pcb->Add( t );
            net_code = t->GetNet();
        }
        delete list;

#if !defined(GERBVIEW)
        test_1_net_connexion( DC, net_code );
#endif
        m_Pcb->DisplayInfo( this );
        break;

#if !defined(GERBVIEW)
    case TYPE_MODULE:
        // Erase general rastnest if needed
        if( g_Show_Ratsnest )
            DrawGeneralRatsnest( DC );

        m_Pcb->Add( item );

        item->Draw( DrawPanel, DC, GR_OR );

        item->SetState( DELETED, OFF );     /* Creal DELETED flag */
        item->m_Flags   = 0;
        GetBoard()->m_Status_Pcb = 0;
        GetBoard()->Build_Pads_Full_List();
        ReCompile_Ratsnest_After_Changes( DC );
        break;
#endif

    default:
        DisplayError( this, wxT( "WinEDA_PcbFrame::UnDeleteItem(): unexpected Struct type" ) );
        delete item;
        break;
    }
}


/* Sauvegarde d'un element aux fins de restitution par Undelete
 *  Supporte actuellement : Module et segments de piste
 */
BOARD_ITEM* WinEDA_BasePcbFrame::SaveItemEfface( BOARD_ITEM* aItem, int nbitems )
{
    if( aItem == NULL || nbitems == 0 )
        return NULL;

    if( g_UnDeleteStackPtr >= UNDELETE_STACK_SIZE )
    {
        // Delete last deleted item, and shift stack.
        delete g_UnDeleteStack[0];

        for( int ii = 0; ii < (g_UnDeleteStackPtr - 1); ii++ )
        {
            g_UnDeleteStack[ii] = g_UnDeleteStack[ii + 1];
        }

        g_UnDeleteStackPtr--;;
    }

    switch( aItem->Type() )
    {
    case TYPE_VIA:
    case TYPE_TRACK:
        {
            DLIST<TRACK>* container = (DLIST<TRACK>*) aItem->GetList();
            wxASSERT( container );

            if( nbitems == 1 )
            {
                container->Remove( (TRACK*) aItem );
                g_UnDeleteStack[g_UnDeleteStackPtr++] = aItem;
            }
            else
            {
                BOARD_ITEM_LIST* list = new BOARD_ITEM_LIST();
                g_UnDeleteStack[g_UnDeleteStackPtr++] = list;

                // copy the numerous tracks into the list, which is already on stack
                int i = 0;
                TRACK* next;
                for( TRACK* track = (TRACK*) aItem;  track && i<nbitems;  track = next, ++i )
                {
                    next = track->Next();
                    list->PushBack( container->Remove( track ) );
                }
            }
        }
        break;

#if !defined(GERBVIEW)
    case TYPE_MODULE:
        {
            MODULE* module = (MODULE*) aItem;
            m_Pcb->m_Modules.Remove( module );
            module->SetState( DELETED, ON );
            g_UnDeleteStack[g_UnDeleteStackPtr++] = module;
            GetBoard()->m_Status_Pcb = 0;
            GetBoard()->Build_Pads_Full_List();
        }
        break;
#endif

    default:
        break;
    }

    // don't know why this is not simply return aItem?
    return g_UnDeleteStack[g_UnDeleteStackPtr - 1];
}
