#include <libraries/mui.h>

/* Protos */
#include <clib/muimaster_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>

/* Pragmas */
#include <pragmas/muimaster_pragmas.h>
#include <pragmas/exec_pragmas.h>

/* ChordPro */
#include "ChordPro.h"

/* MUIBuilder */
#include "Window.h"

#define ID_1ST 1      /*  A  On */
#define ID_2ND 2      /*  A# On */
#define ID_3RD 3      /*  B  On */
#define ID_4TH 4      /*  C  On */
#define ID_5TH 5      /*  C  On */
#define ID_6TH 6      /*  D  On */
#define ID_7TH 7      /*  D# On */
#define ID_8TH 8      /*  E  On */
#define ID_9TH 9      /*  F  On */
#define ID_10TH 10    /*  F# On */
#define ID_11TH 11    /*  G  On */
#define ID_12TH 12    /*  G# On */

#define ID_START 13   /*  Start Search */
#define ID_QUIT 14    /*  Quit */
#define ID_ABOUT 15   /*  About */   
#define ID_CHORDA 16  /*  Exact Chord Chosen */
#define ID_CHORDB 17  /*  Oneout Chord Chosen */
#define ID_CHORDC 18  /*  Twoout Chord Chosen */
#define ID_CHORDCLOSE 19 /* Chord Window Close */

#define ID_1STOF 21   /*  A  Off */
#define ID_2NDOF 22   /*  A# Off */
#define ID_3RDOF 23   /*  B  Off */
#define ID_4THOF 24   /*  C  Off */
#define ID_5THOF 25   /*  C  Off */
#define ID_6THOF 26   /*  D  Off */
#define ID_7THOF 27   /*  D# Off */
#define ID_8THOF 28   /*  E  Off */
#define ID_9THOF 29   /*  F  Off */
#define ID_10THOF 30  /*  F# Off */
#define ID_11THOF 31  /*  G  Off */
#define ID_12THOF 32  /*  G# Off */

struct Library * MUIMasterBase;
char *tonal_board[12];
char *inter_board[12];

CHORD_LIST head_of_chords;
FOUND_LIST head_of_founds;

/* Init Function */
static void init(void)
{

   if (!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
   {
      printf("Can't Open MUIMaster Library"); 
      exit(20);
   }

}

main()
{

   inter_board[0] = inter_board[2] = inter_board[4] = inter_board[5] = inter_board[7] = inter_board[9] = inter_board[11];
   inter_board[1] = inter_board[3] = inter_board[6] = inter_board[8] = inter_board[10];
   tonal_board[0] = tonal_board[2] = tonal_board[3] = tonal_board[5] = tonal_board[7] = tonal_board[8] = tonal_board[10] = calloc(2, sizeof(char));
   tonal_board[1] = tonal_board[4] = tonal_board[6] = tonal_board[9] = tonal_board[11] = calloc(3, sizeof(char));

   tonal_board[0] = "A\0";
   inter_board[0] = "R\0";
   tonal_board[1] = "A#\0";
   inter_board[1] = "b2\0";
   tonal_board[2] = "B\0";
   inter_board[2] = "2\0";
   tonal_board[3] = "C\0";
   inter_board[3] = "b3\0";
   tonal_board[4] = "C#\0";
   inter_board[4] = "3\0";
   tonal_board[5] = "D\0";
   inter_board[5] = "4\0";
   tonal_board[6] = "D#\0";
   inter_board[6] = "b5\0";
   tonal_board[7] = "E\0";
   inter_board[7] = "5\0";
   tonal_board[8] = "F\0";
   inter_board[8] = "b6\0";
   tonal_board[9] = "F#\0";
   inter_board[9] = "6\0";
   tonal_board[10] = "G\0";
   inter_board[10] ="b7\0";
   tonal_board[11] = "G#\0";
   inter_board[11] = "7\0";
   
   struct ObjApp * App = NULL;
   BOOL running = TRUE;
   ULONG signal;
   extern struct ObjApp * CreateSmall_Example(void);
   char *STR_MessageAbout = "\0338\033c ChordMaster v1.0 by Chris Carr 1995";
   char *STR_MessageStart = "\0338\033c Searching...";
   char *STR_MessageFound = "\0338\033c Search Complete";
   char *STR_MessageNumber = "\0338\033c No Notes Selected - Need At Least One Note";
   char *main_encoding = "000000000000\0";
   int nm_notes = 0;
   int count = 0;
   int found = 0;
   head_of_chords = read_chords();
   char *buf = calloc(20, sizeof(char));
   char *buf2 = calloc(20, sizeof(char)); 
   char *buf3 = calloc(20, sizeof(char));
   char *notes0 = calloc(30, sizeof(char));
   char *inter0 = calloc(30, sizeof(char));
   char *temp = calloc(20, sizeof(char));
   buf = buf2 = buf3 = "                   \0";
   notes0 =  "                            \0";
   
   FOUND_LIST current_found;

   init();

   App = CreateApp();

   DoMethod(App->Chord_Pro_Window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App->App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
   DoMethod(App->Note0, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_1STOF);
   DoMethod(App->Note1, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_2NDOF);
   DoMethod(App->Note2, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_3RDOF);
   DoMethod(App->Note3, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_4THOF);
   DoMethod(App->Note4, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_5THOF);
   DoMethod(App->Note5, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_6THOF);
   DoMethod(App->Note6, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_7THOF);
   DoMethod(App->Note7, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_8THOF);
   DoMethod(App->Note8, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_9THOF);
   DoMethod(App->Note9, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_10THOF);
   DoMethod(App->Note10, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_11THOF);  
   DoMethod(App->Note11, MUIM_Notify, MUIA_Selected, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_12THOF);

   DoMethod(App->Note0, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_1ST);
   DoMethod(App->Note1, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_2ND);
   DoMethod(App->Note2, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_3RD);
   DoMethod(App->Note3, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_4TH);
   DoMethod(App->Note4, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_5TH);
   DoMethod(App->Note5, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_6TH);
   DoMethod(App->Note6, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_7TH);
   DoMethod(App->Note7, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_8TH);
   DoMethod(App->Note8, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_9TH);
   DoMethod(App->Note9, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_10TH);
   DoMethod(App->Note10, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_11TH);  
   DoMethod(App->Note11, MUIM_Notify, MUIA_Selected, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_12TH);

   DoMethod(App->StartButton, MUIM_Notify, MUIA_Pressed, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_START);
   DoMethod(App->QuitButton, MUIM_Notify, MUIA_Pressed, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_QUIT);
   DoMethod(App->AboutButton, MUIM_Notify, MUIA_Pressed, FALSE, App->App, 2, MUIM_Application_ReturnID, ID_ABOUT);
  /*  DoMethod(App->Chord_Info_Window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App->Chord_Info_Window, 3, MUIM_Set, MUIA_Window_Open,FALSE); */
   DoMethod(App->Chord_Info_Window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_CHORDCLOSE);
   DoMethod(App->ExactList, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_CHORDA);
   DoMethod(App->OneOutList, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_CHORDB);
   DoMethod(App->TwoOutList, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE, App->App, 2, MUIM_Application_ReturnID, ID_CHORDC);

   set(App->Chord_Pro_Window, MUIA_Window_Open, TRUE);

   while (running)
   {
      switch(DoMethod(App->App, MUIM_Application_Input, &signal))
      {
         case ID_1ST:
            /* printf("A Chosen\n"); */
            main_encoding[0] = '1';
            nm_notes += 1;
            break;
         case ID_2ND:
            /* printf("A# Chosen\n"); */
            main_encoding[1] = '1';
            nm_notes += 1;
            break;
         case ID_3RD:
            /* printf("B Chosen\n"); */
            main_encoding[2] = '1';
            nm_notes += 1;
            break;
         case ID_4TH:
            /* printf("C Chosen\n"); */
            main_encoding[3] = '1';
            nm_notes += 1;
            break;
         case ID_5TH:
            /* printf("C# Chosen\n"); */
            main_encoding[4] = '1';
            nm_notes += 1;
            break;
         case ID_6TH:
            /* printf("D Chosen\n"); */
            main_encoding[5] = '1';
            nm_notes += 1;
            break;
         case ID_7TH:
            /* printf("D# Chosen\n"); */
            main_encoding[6] = '1';
            nm_notes += 1;
            break;
         case ID_8TH:
            /* printf("E Chosen\n"); */
            main_encoding[7] = '1';
            nm_notes += 1;
            break;
         case ID_9TH:
            /* printf("F Chosen\n"); */
            main_encoding[8] = '1';
            nm_notes += 1;
            break;
         case ID_10TH:
            /* printf("F# Chosen\n"); */
            main_encoding[9] = '1';
            nm_notes += 1;
            break;
         case ID_11TH:
            /* printf("G Chosen\n"); */
            main_encoding[10] = '1';
            nm_notes += 1;
            break;
         case ID_12TH:
            /* printf("G# Chosen\n"); */
            main_encoding[11] = '1';
            nm_notes += 1;
            break;
         case ID_1STOF:
            /* printf("A UnChosen\n"); */
            main_encoding[0] = '0';
            nm_notes -= 1;
            break;
         case ID_2NDOF:
            /* printf("A# UnChosen\n"); */
            main_encoding[1] = '0';
            nm_notes -= 1;
            break;
         case ID_3RDOF:
            /* printf("B UnChosen\n"); */
            main_encoding[2] = '0';
            nm_notes -= 1;
            break;
         case ID_4THOF:
            /* printf("C UnChosen\n"); */
            main_encoding[3] = '0';
            nm_notes -= 1;
            break;
         case ID_5THOF:
            /* printf("C# UnChosen\n"); */
            main_encoding[4] = '0';
            nm_notes -= 1;
            break;
         case ID_6THOF:
            /* printf("D UnChosen\n"); */
            main_encoding[5] = '0';
            nm_notes -= 1;
            break;
         case ID_7THOF:
            /* printf("D# UnChosen\n"); */
            main_encoding[6] = '0';
            nm_notes -= 1;
            break;
         case ID_8THOF:
            /* printf("E UnChosen\n"); */
            main_encoding[7] = '0';
            nm_notes -= 1;
            break;
         case ID_9THOF:
            /* printf("F UnChosen\n"); */
            main_encoding[8] = '0';
            nm_notes -= 1;
            break;
         case ID_10THOF:
            /* printf("F# UnChosen\n"); */
            main_encoding[9] = '0';
            nm_notes -= 1;
            break;
         case ID_11THOF:
            /* printf("G UnChosen\n"); */
            main_encoding[10] = '0';
            nm_notes -= 1;
            break;
         case ID_12THOF:
            /* printf("G# UnChosen\n"); */
            main_encoding[11] = '0';
            nm_notes -= 1;
            break;
         case ID_START:
            if (nm_notes > 0)
            {
               set(App->Info, MUIA_Text_Contents, STR_MessageStart);
               DoMethod(App->ExactList, MUIM_List_Clear);
               DoMethod(App->OneOutList, MUIM_List_Clear);
               DoMethod(App->TwoOutList, MUIM_List_Clear);
               start_search(main_encoding, nm_notes);
               current_found = head_of_founds;
               while (current_found != NULL)
               {
                  if (current_found->match == 0)
                  {
                     strcpy(temp, current_found->full_chord_name);
                     /* printf("Name = %s\n", temp); */
                     DoMethod(App->ExactList, MUIM_List_Insert, &temp, 1, MUIV_List_Insert_Bottom);    
                  }
                  else if (current_found->match ==1 )
                  {
                     strcpy(temp, current_found->full_chord_name);
                     /* printf("Name = %s\n", temp); */
                     DoMethod(App->OneOutList, MUIM_List_Insert, &temp, 1, MUIV_List_Insert_Bottom);    
                  }
                  else if (current_found->match == 2)
                  {
                     strcpy(temp, current_found->full_chord_name);
                     /* printf("Name = %s\n", temp); */
                     DoMethod(App->TwoOutList, MUIM_List_Insert, &temp, 1, MUIV_List_Insert_Bottom);    
                  }
                  /* printf("Name %s, Notes %s, Match %d\n", current_found->full_chord_name, current_found->chord_notes, current_found->match); */
                  current_found = current_found->next;
               }
               set(App->Info, MUIA_Text_Contents, STR_MessageFound);
               break;
            }
            else
            {
               set(App->Info, MUIA_Text_Contents, STR_MessageNumber);
               break;
            }
         case ID_ABOUT:
            /* printf("About Chosen\n"); */
            set(App->Info, MUIA_Text_Contents, STR_MessageAbout); 
            break;
         case ID_CHORDA:
            found = 0;
            set(App->Chord_Info_Window, MUIA_Window_Open, TRUE);
            DoMethod(App->ExactList, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &buf);
            set(App->Chord_Pro_Window, MUIA_Window_Sleep, TRUE);
            current_found = head_of_founds;
            while ((current_found != NULL) && (found != 1))
            {
               if (!(strcmp(buf, current_found->full_chord_name)))
               {
                  found = 1;
                  strcpy(notes0, current_found->chord_notes);
                  strcpy(inter0, current_found->intervals);
                  break;
               }
               current_found = current_found->next;
            }
            set(App->Chord_Name_Box, MUIA_Text_Contents, buf);
            set(App->Chord_Notes_Box, MUIA_Text_Contents, notes0);
            set(App->Chord_Intervals_Box, MUIA_Text_Contents, inter0);
            break;
         case ID_CHORDB:
            found = 0;
            DoMethod(App->OneOutList, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &buf2);
            set(App->Chord_Info_Window, MUIA_Window_Open, TRUE);
            set(App->Chord_Pro_Window, MUIA_Window_Sleep, TRUE);            
            current_found = head_of_founds;
            while ((current_found != NULL) && (found != 1))
            {
               if (!(strcmp(buf2, current_found->full_chord_name)))
               {
                  found = 1;
                  strcpy(notes0, current_found->chord_notes);
                  strcpy(inter0, current_found->intervals);
                  break;
               }
               current_found = current_found->next;
            }
            set(App->Chord_Name_Box, MUIA_Text_Contents, buf2);
            set(App->Chord_Notes_Box, MUIA_Text_Contents, notes0);
            set(App->Chord_Intervals_Box, MUIA_Text_Contents, inter0);
            break;
         case ID_CHORDC:
            found = 0;
            set(App->Chord_Info_Window, MUIA_Window_Open, TRUE);  
            DoMethod(App->TwoOutList, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &buf3);
            set(App->Chord_Pro_Window, MUIA_Window_Sleep, TRUE);
            set(App->Chord_Name_Box, MUIA_Text_Contents, buf3);
            current_found = head_of_founds;
            while ((current_found != NULL) && (found != 1))
            {
               if (!(strcmp(buf3, current_found->full_chord_name)))
               {
                  found = 1;
                  strcpy(notes0, current_found->chord_notes);
                  strcpy(inter0, current_found->intervals);
                  break;
               }
               current_found = current_found->next;
            }
            set(App->Chord_Notes_Box, MUIA_Text_Contents, notes0);
            set(App->Chord_Intervals_Box, MUIA_Text_Contents, inter0);
            break;
         case ID_CHORDCLOSE:
            set(App->Chord_Info_Window, MUIA_Window_Open, FALSE);
            set(App->Chord_Pro_Window, MUIA_Window_Sleep, FALSE);
            break;
         case ID_QUIT:
            running = FALSE;
            break;
         case MUIV_Application_ReturnID_Quit:
            running = FALSE;
            break;
      }

      if (running && signal) Wait(signal);
   }

   DisposeApp(App);
   CloseLibrary(MUIMasterBase);
   exit(0);

}   

/***********************************************************************/
/* Procedure : read_chords                                             */
/* Purpose   : create the list of chords                               */
/* Inputs    : none                                                    */
/* Outputs   : CHORD_LIST - the head of the created list               */
/* Notes     :                                                         */
/***********************************************************************/

CHORD_LIST read_chords(void)
{

   CHORD_LIST head = NULL, tail;
   FILE *ifp;
   char c;
   int namepos, encodingpos, current_encoding, current_name;
   current_encoding = 1;
   current_name = 0;
   namepos = encodingpos = 0;
   char *temp_name;
   char *temp_enco;
   temp_name = calloc(20, sizeof(char));
   temp_enco = calloc(13, sizeof(char));

   ifp = fopen("testfile-a.txt", "r");

   while ((c = getc(ifp)) != EOF)
   {
      if (c== ',')
      {
         current_encoding = 0;
         current_name = 1;
         temp_enco[encodingpos] = '\0';
      }
      else if (c == '!')
      {
         temp_name[namepos] = '\0';
         current_name = 0;
         current_encoding = 1;
         head = malloc(sizeof(CHORD_ELEMENT));
         head->name = calloc(20, sizeof(char));
         head->encoding = calloc(13, sizeof(char));
         strcpy(head->encoding, temp_enco);        
         strcpy(head->name, temp_name);
         tail = head;
      }
      else if (c == '&')
      {
         temp_name[namepos] = '\0';
         current_name = 0;
         current_encoding = 1;
         tail->next = malloc(sizeof(CHORD_ELEMENT));
         tail = tail->next;
         tail->name = calloc(20, sizeof(char));
         tail->encoding = calloc(13, sizeof(char));
         strcpy(tail->encoding, temp_enco);
         strcpy(tail->name, temp_name);
      }
      else if (c == '?')
      {
         temp_name[namepos] = '\0';
         tail->next = malloc(sizeof(CHORD_ELEMENT));
         tail = tail->next;
         tail->name = calloc(20, sizeof(char));
         tail->encoding = calloc(13, sizeof(char));
         strcpy(tail->encoding, temp_enco);        
         strcpy(tail->name, temp_name);
         tail->next = NULL;
      }
      else if (c == '\n')
      {
         current_name = 0;
         current_encoding = 1;
         encodingpos = namepos = 0;
      }
      else if (current_encoding)
      {
         temp_enco[encodingpos] = c;
         ++encodingpos;
      }
      else if (current_name)
      {
         temp_name[namepos] = c;
         ++namepos;
      }
   }
 
   fclose(ifp);
  
   return head;

}

