#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>
#include <clib/gadtools_protos.h>
#include <string.h>
#include "mcdplayer.h"

#define GD_ProgTitelliste                      0
#define GD_ProgSave                            1
#define GD_ProgAbbruch                         2
#define GD_ProgBenutzen                        3
#define GD_ProgProgliste                       4
#define GD_ProgNeu                             5
#define GD_ProgEditMode                        6
#define GD_ProgEditNum                         7

extern struct MsgPort     *TimerMP;

APTR                  VisualInfo = NULL;
struct Screen        *Scr;
struct Window        *ProgWnd = NULL;
struct Gadget        *ProgGList = NULL;
struct Gadget        *ProgGadgets[8];
WORD                  ProgLeft;
WORD                  ProgTop;
UWORD                 ProgWidth = 469;
UWORD                 ProgHeight = 174;
UBYTE                *ProgWdt = (UBYTE *)"Title List";

struct List           SongList;
struct Node           SongNode[100];
struct List           PrgList;
struct Node           PrgNode[100];
char                 *SongTitles;

int                   ProgLen = 0;
int                   ProgPos = 0;
int                   ProgNr = 0;
int                   ProgEditMode = 0;

BYTE                  Program[100][9];
BYTE                  TempProg[100][9];

UBYTE         *ProgEditModeLabels[] = {
    (UBYTE *)"Delete",
    (UBYTE *)"Up",
    (UBYTE *)"Down",
    (UBYTE *)"Top",
    (UBYTE *)"Bottom",
    NULL };

UBYTE         *ProgEditNumLabels[] = {
    (UBYTE *)"Start",
    (UBYTE *)"Prog 1",
    (UBYTE *)"Prog 2",
    (UBYTE *)"Prog 3",
    (UBYTE *)"Prog 4",
    (UBYTE *)"Prog 5",
    (UBYTE *)"Prog 6",
    (UBYTE *)"Prog 7",
    (UBYTE *)"Prog 8",
    NULL };

struct TextAttr topaz8 = {
    ( STRPTR )"topaz.font", 8, 0x00, 0x41 };

void MakePrgList( int Nr )
    {
    int i;

    NewList( &PrgList );
    i = 0;
    while( TempProg[i][Nr] )
        {
        PrgNode[i].ln_Name = SongNode[TempProg[i][Nr]-1].ln_Name;
        PrgNode[i].ln_Pri  = TempProg[i][Nr];
        AddTail( &PrgList, &PrgNode[i] );
        i++;
        };
    ProgLen = i;
    ProgNr = Nr;
    };

void GetProgram( void )
    {
    char Buffer[256];
    BPTR FH;
    int i;

    sprintf( Buffer, SongPath );
    AddPart( Buffer, TOC_CDID, 130 );
    Buffer[strlen(Buffer)-16] = 'p';
    Buffer[strlen(Buffer)-15] = 'r';

    if (FH = Open( Buffer, MODE_OLDFILE ))
        {
        Read( FH, Program, 900 );
        Close( FH );
        }
    else
        {
        for( i=0; i<=8; i++ ) Program[0][i] = 0;
        };
    }

void InitLists( void )
    {
    int i;

    if (SongTitles = AllocMem( 10000, MEMF_ANY|MEMF_CLEAR ))
        {
        NewList( &SongList );
        for( i=0; i<TOC_NumTracks; i++ )
            {
            SongNode[i].ln_Name = &(SongTitles[i*100]);
            sprintf( &(SongTitles[i*100]), "%02d: ", i+1 );
            strcpy( &(SongTitles[i*100+4]), TOC_Title[i] );
            AddTail( &SongList, &SongNode[i] );
            };
        memcpy( TempProg, Program, 900 );
        MakePrgList( 0 );
        }
    }

void ExitLists( int Action ) /* 0=Exit, 1=Use, 2=Save */
    {
    char Buffer[256];
    BPTR FH;

    if (Action)
        {
        memcpy( Program, TempProg, 900 );
        }
        
    if (Action==2)
        {
        sprintf( Buffer, SongPath );
        AddPart( Buffer, TOC_CDID, 130 );
        Buffer[strlen(Buffer)-16] = 'p';
        Buffer[strlen(Buffer)-15] = 'r';

        if (FH = Open( Buffer, MODE_NEWFILE ))
            {
            Write( FH, Program, 900 );
            Close( FH );
            }
        }

    if (SongTitles) FreeMem( SongTitles, 10000 );
    }

int OpenProgWindow( void )
{
    struct NewGadget     ng;
    struct Gadget       *g;
    UWORD               offx, offy;

    if ( ! ( Scr = LockPubScreen( 0 )))
        return( 1L );

    PlaceWnd( Scr, ProgWidth, ProgHeight + offy, &ProgLeft, &ProgTop, 0 );

    if ( ! ( VisualInfo = GetVisualInfo( Scr, TAG_DONE )))
        return( 2L );

    offx = Scr->WBorLeft;
    offy = Scr->WBorTop + Scr->RastPort.TxHeight + 1;

    if ( ! ( g = CreateContext( &ProgGList )))
        return( 1L );

    ng.ng_LeftEdge        =    offx + 5;
    ng.ng_TopEdge         =    offy + 19;
    ng.ng_Width           =    181;
    ng.ng_Height          =    128;
    ng.ng_GadgetText      =    (UBYTE *)"Title List";
    ng.ng_TextAttr        =    &topaz8;
    ng.ng_GadgetID        =    GD_ProgTitelliste;
    ng.ng_Flags           =    PLACETEXT_ABOVE;
    ng.ng_VisualInfo      =    VisualInfo;

    g = CreateGadget( LISTVIEW_KIND, g, &ng, GTLV_Labels, &SongList, GTLV_ShowSelected, NULL, TAG_DONE );

    ProgGadgets[ 0 ] = g;

    ng.ng_TopEdge         =    offy + 153;
    ng.ng_Width           =    80;
    ng.ng_Height          =    14;
    ng.ng_GadgetText      =    (UBYTE *)"Save";
    ng.ng_GadgetID        =    GD_ProgSave;
    ng.ng_Flags           =    PLACETEXT_IN;

    g = CreateGadget( BUTTON_KIND, g, &ng, TAG_DONE );

    ProgGadgets[ 1 ] = g;

    ng.ng_LeftEdge        =    offx + 375;
    ng.ng_GadgetText      =    (UBYTE *)"Cancel";
    ng.ng_GadgetID        =    GD_ProgAbbruch;

    g = CreateGadget( BUTTON_KIND, g, &ng, TAG_DONE );

    ProgGadgets[ 2 ] = g;

    ng.ng_LeftEdge        =    offx + 190;
    ng.ng_GadgetText      =    (UBYTE *)"Use";
    ng.ng_GadgetID        =    GD_ProgBenutzen;

    g = CreateGadget( BUTTON_KIND, g, &ng, TAG_DONE );

    ProgGadgets[ 3 ] = g;

    ng.ng_LeftEdge        =    offx + 274;
    ng.ng_TopEdge         =    offy + 19;
    ng.ng_Width           =    181;
    ng.ng_Height          =    128;
    ng.ng_GadgetText      =    (UBYTE *)"Program List";
    ng.ng_GadgetID        =    GD_ProgProgliste;
    ng.ng_Flags           =    PLACETEXT_ABOVE;

    g = CreateGadget( LISTVIEW_KIND, g, &ng, GTLV_Labels, &PrgList, GTLV_ShowSelected, NULL, TAG_DONE );

    ProgGadgets[ 4 ] = g;

    ng.ng_LeftEdge        =    offx + 190;
    ng.ng_Width           =    80;
    ng.ng_Height          =    14;
    ng.ng_GadgetText      =    (UBYTE *)"New";
    ng.ng_GadgetID        =    GD_ProgNeu;
    ng.ng_Flags           =    PLACETEXT_IN;

    g = CreateGadget( BUTTON_KIND, g, &ng, TAG_DONE );

    ProgGadgets[ 5 ] = g;

    ng.ng_TopEdge         =    offy + 36;
    ng.ng_GadgetText      =    NULL;
    ng.ng_GadgetID        =    GD_ProgEditMode;
    ng.ng_Flags           =    0;

    g = CreateGadget( CYCLE_KIND, g, &ng, GTCY_Labels, &ProgEditModeLabels[0], TAG_DONE );

    ProgGadgets[ 6 ] = g;

    ng.ng_LeftEdge        =    offx + 193;
    ng.ng_TopEdge         =    offy + 57;
    ng.ng_GadgetID        =    GD_ProgEditNum;
    ng.ng_Flags           =    PLACETEXT_RIGHT;

    g = CreateGadget( MX_KIND, g, &ng, GTMX_Labels, &ProgEditNumLabels[0], TAG_DONE );

    ProgGadgets[ 7 ] = g;

    if ( ! g )
        return( 2L );

    if ( ! ( ProgWnd = OpenWindowTags( NULL,
                    WA_Left,          ProgLeft,
                    WA_Top,           ProgTop,
                    WA_Width,         ProgWidth,
                    WA_Height,        ProgHeight + offy,
                    WA_IDCMP,         LISTVIEWIDCMP|BUTTONIDCMP|CYCLEIDCMP|MXIDCMP|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW,
                    WA_Flags,         WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
                    WA_Gadgets,       ProgGList,
                    WA_Title,         ProgWdt,
                    WA_PubScreen,     Scr,
                    TAG_DONE )))
        return( 4L );

    GT_RefreshWindow( ProgWnd, NULL );

    return( 0L );
}

void CloseProgWindow( void )
{
    if ( ProgWnd        )
        {
        CloseWindow( ProgWnd );
        ProgWnd = NULL;
        }

    if ( ProgGList      )
        {
        FreeGadgets( ProgGList );
        ProgGList = NULL;
        }

    if ( VisualInfo )
        {
        FreeVisualInfo( VisualInfo );
        VisualInfo = NULL;
        }

    if ( Scr )
        {
        UnlockPubScreen( NULL, Scr );
        }
}

void ProgList( void )
    {
/*    ULONG  GClass;
    USHORT GCode;
    struct Gadget *GList = 0l;
    struct IntuiMessage  *msg;
    int Exit = 0;
    int i;
    BYTE a;
    LONG Sig;
*/
    InitLists();
    if (OpenProgWindow()) {CloseProgWindow();ExitLists(0);}
};

void Handle_ProgInput(void)
{
    struct IntuiMessage  *msg;
    ULONG  GClass;
    USHORT GCode;
    struct Gadget* GList;
    int i;
    BYTE a;

    while (msg = (struct IntuiMessage *) GT_GetIMsg( ProgWnd->UserPort ) )
    {
       GClass  = msg->Class;
       GCode   = msg->Code;
       if (GClass & (GADGETDOWN | GADGETUP | MOUSEMOVE) )
           GList   = (struct Gadget *) msg->IAddress;
           GT_ReplyIMsg(msg);

           switch (GClass)
              {
              case IDCMP_CLOSEWINDOW:
                 ExitLists(0);
                 CloseProgWindow();
                 return;
              case IDCMP_GADGETUP:
                 switch (GList->GadgetID)
                    {
                    case GD_ProgTitelliste:
                       if (ProgLen<100)
                       {
                          GT_SetGadgetAttrs(ProgGadgets[GD_ProgProgliste], ProgWnd, 0, GTLV_Labels, ~0, TAG_DONE);
                          TempProg[ProgLen][ProgNr] = GCode + 1;
                          TempProg[ProgLen+1][ProgNr] = 0;
                          MakePrgList( ProgNr );
                          GT_SetGadgetAttrs(ProgGadgets[GD_ProgProgliste], ProgWnd, 0, GTLV_Labels, &PrgList, TAG_DONE);
                       };
                       break;
                    case GD_ProgSave      :
                       ExitLists(2);
                       CloseProgWindow();
                       return;
                    case GD_ProgAbbruch   :
                       ExitLists(0);
                       CloseProgWindow();
                       return;
                    case GD_ProgBenutzen  :
                       ExitLists(1);
                       CloseProgWindow();
                       return;
                    case GD_ProgProgliste :
                       GT_SetGadgetAttrs(ProgGadgets[GD_ProgProgliste], ProgWnd, 0, GTLV_Labels, ~0, TAG_DONE);
                       switch (ProgEditMode)
                          {
                          case 0: i = GCode;
                             while( TempProg[i][ProgNr] )
                             {
                                TempProg[i][ProgNr] = TempProg[i+1][ProgNr];
                                i++;
                             };
                             break;
                          case 1: if (GCode>0)
                             {
                                a = TempProg[GCode][ProgNr];
                                TempProg[GCode][ProgNr] = TempProg[GCode-1][ProgNr];
                                TempProg[GCode-1][ProgNr] = a;
                             }
                             break;
                          case 2: if (GCode<ProgLen-1)
                             {
                                a = TempProg[GCode][ProgNr];
                                TempProg[GCode][ProgNr] = TempProg[GCode+1][ProgNr];
                                TempProg[GCode+1][ProgNr] = a;
                             }
                             break;
                          case 3: a = TempProg[GCode][ProgNr];
                             i = GCode;
                             while (i>0)
                                {
                                TempProg[i][ProgNr] = TempProg[i-1][ProgNr];
                                i--;
                                }
                                TempProg[0][ProgNr] = a;
                             break;
                          case 4: a = TempProg[GCode][ProgNr];
                             i = GCode;
                             while( TempProg[i+1][ProgNr] )
                                {
                                TempProg[i][ProgNr] = TempProg[i+1][ProgNr];
                                i++;
                                };
                             TempProg[i][ProgNr] = a;
                             break;
                          }
                       MakePrgList( ProgNr );
                       GT_SetGadgetAttrs(ProgGadgets[GD_ProgProgliste], ProgWnd, 0, GTLV_Labels, &PrgList, TAG_DONE);
                       break;
                    case GD_ProgNeu       :
                       GT_SetGadgetAttrs(ProgGadgets[GD_ProgProgliste], ProgWnd, 0, GTLV_Labels, ~0, TAG_DONE);
                       TempProg[0][ProgNr] = 0;
                       MakePrgList( ProgNr );
                       GT_SetGadgetAttrs(ProgGadgets[GD_ProgProgliste], ProgWnd, 0, GTLV_Labels, &PrgList, TAG_DONE);
                       break;
                    case GD_ProgEditMode  :
                       ProgEditMode = GCode;
                       break;
                    };
                    break;
                 case IDCMP_GADGETDOWN:
                    switch (GList->GadgetID)
                    {
                       case GD_ProgEditNum   :
                          GT_SetGadgetAttrs(ProgGadgets[GD_ProgProgliste], ProgWnd, 0, GTLV_Labels, ~0, TAG_DONE);
                          MakePrgList( GCode );
                          GT_SetGadgetAttrs(ProgGadgets[GD_ProgProgliste], ProgWnd, 0, GTLV_Labels, &PrgList, TAG_DONE);
                          break;
                    };
                 break;
                 };
              };
           }

