#include "allegro.h"
#include "seal.h"
#include "app.h"
#include "beditor.h"
#include "iodlg.h"
#include "menus.h"
/* jdh - sorry, I took out the stuff for the new blank application.
  Mostly because I couldn't tell which was program and which was
  the program in the program. Another reason was that it specified
  the name main for a global window struct, which gives gcc -Wall
  reason to complain. main is normally the name of the main() function.
  Indeed there IS a slight ambiguity when the dlx loader loads the program
  because main is already defined in seal.exe. It's only the fact main
  isn't in its LIBEXPORT list that allows load_dlx to load the program.
  In any event it's probably better to have it in an external file rather 
  than hardcode it into the app.
*/

typedef struct t_error_listbox_item *p_error_listbox_item;

typedef struct t_error_listbox_item {

   struct t_listbox_item   obclass;

   l_long   line;

} t_error_listbox_item;


#define free_error_listbox_item   free_listbox_item
#include "viscomp.c"

#define MSG_NEW 100001
#define MSG_OPEN 100002
#define MSG_SAVE 100003
#define MSG_SAVEAS 100004

#define MSG_NEW_BLANK_APP 200001
#define MSG_COMPILE 200002
#define MSG_RUN 200003

#define MSG_ABOUT 300001

#ifdef Bad_Seal
static DATAFILE *dat = NULL;
#endif

static l_text current_path = NULL;
static l_text current_file = NULL;

p_appwin mainwin = NULL;
p_beditor edit = NULL;
p_stattext status = NULL;

static p_list get_file_items()
{
  p_list p = list_init(malloc(sizeof(t_list)), &free_filehistory_item, 0);

  if (p) {
     p->insert(p, new_filehistory_item("Text files (*.txt)", "*.txt"));
     p->insert(p, new_filehistory_item("Info files (*.inf)", "*.inf"));
     p->insert(p, new_filehistory_item("INI files (*.ini)", "*.ini"));
     p->insert(p, new_filehistory_item("SealScript files (*.ss)", "*.ss"));
     p->insert(p, new_filehistory_item("HTML source code (*.htm)", "*.htm"));
     p->insert(p, new_filehistory_item("C sources (*.c)", "*.c"));
     p->insert(p, new_filehistory_item("ANSI C sources (*.cc)", "*.cc"));
     p->insert(p, new_filehistory_item("C headers (*.h)", "*.h"));
     p->insert(p, new_filehistory_item("SEAL export files (*.exp)", "*.exp"));
     p->insert(p, new_filehistory_item("Configuration files (*.cfg)", "*.cfg"));
     p->insert(p, new_filehistory_item("Application lists (*.set)", "*.set"));
     p->insert(p, new_filehistory_item("Pascal sources (*.pas)", "*.pas"));
     p->insert(p, new_filehistory_item("BASIC sources (*.bas)", "*.bas"));
     p->insert(p, new_filehistory_item("SealBasic sources (*.sb)", "*.sb"));
     p->insert(p, new_filehistory_item("All files (*.*)", "*.*"));
  };

  return p;
}

static p_menu bedit_menu()
{
  p_menu menu = new_menu(
    new_sub_menu("File", new_menu(
      new_menu_item("New document", "", 0, MSG_NEW, NULL,
      new_menu_item("Open document...", "", 0, MSG_OPEN, NULL,
      new_menu_item("Save document", "", 0, MSG_SAVE, NULL,
      new_menu_item("Save document as...", "", 0, MSG_SAVEAS, NULL,
      new_menu_line(
      new_menu_item("Quit BEdit...", "ALT+F4", TO_ALT(KB_F4), MSG_CLOSE, NULL,
    NULL))))))),
    new_sub_menu("Developing", new_menu(
      new_menu_item("New blank application", "", 0, MSG_NEW_BLANK_APP, NULL,
      new_menu_line(
      new_menu_item("Compile", "F9", TO_KEY(KB_F9), MSG_COMPILE, NULL,
      new_menu_item("Run", "Ctrl+F9", TO_ALT(KB_F9), MSG_RUN, NULL,
    NULL))))),
    new_sub_menu("Help", new_menu(
      new_menu_item("About BEdit...", "", 0, MSG_ABOUT, NULL,
    NULL)),
  NULL))));

  return menu;
};

void redraw_title()
{
  if (mainwin) {
    free(WINDOW(mainwin)->caption);
    if (current_file)
      WINDOW(mainwin)->caption = set_format_text(NULL, "BEdit 1.1 - [%s]", current_file);
    else
      WINDOW(mainwin)->caption = strdup("BEdit 1.1");

    TEST_SUB_VIEWS(VIEW(mainwin), WINDOW(mainwin)->draw_title(WINDOW(mainwin)));
  };
};

l_bool ask_if_modified()
{
  if (!edit->modified) return TRUE;
  return (l_bool)(msgbox(MW_INFO, MB_YES|MB_NO, "Do you want to discard changes?") != MSG_NO);
}

static void trans_ev(p_object o, p_event event)
{
  if (event->type == EV_MESSAGE) {
    switch (event->message) {
      case MSG_CLOSE: {
        t_event oldev = *event;
        if (o->phase == PH_PREPROCESS) {
         if (ask_if_modified()) {
           *event = oldev;
         } else clear_event(event);
        }
      }; break;
      case MSG_NEW: {
        clear_event(event);
        if (ask_if_modified()) {
          edit->modified = FALSE;
          free(current_file);
          current_file = NULL;
          edit->set_text(edit, "");
          redraw_title();
        };
      }; break;
      case MSG_OPEN: {
        l_text file;
        clear_event(event);
        file = open_dialog(current_path, "*.txt", get_file_items());
        if (file && ask_if_modified()) {
          l_text t = file_gettext(file);
          l_text p = io_path(file);
          edit->modified = FALSE;
          free(current_file);
          free(current_path);
          current_file = strdup(file);
          current_path = p;
          edit->set_text(edit, t);
          redraw_title();
          free(t);
        };
        free(file);
      }; break;
      case MSG_SAVE: {
        clear_event(event);
        if (!current_file)
          current_file = save_dialog(current_path, "*.txt", get_file_items());
        if (current_file) {
          edit->modified = FALSE;
          if (!file_puttext(current_file, edit->text))
            seal_error(ERR_INFO, "Cannot save - %s", current_file);
          redraw_title();
        };
      }; break;
      case MSG_SAVEAS: {
        clear_event(event);
        current_file = save_dialog(current_path, "*.txt", get_file_items());
        if (current_file && ask_if_modified()) {
          if (!file_puttext(current_file, edit->text))
            seal_error(ERR_INFO, "Cannot save - %s", current_file);
          else
            edit->modified = FALSE;
          redraw_title();
        };
      }; break;
      case MSG_NEW_BLANK_APP: {
        clear_event(event);
        if (ask_if_modified()) {
          edit->modified = FALSE;
          free(current_file);
          current_file = NULL;
          edit->set_text(edit, "");
          redraw_title();
        }
      }; break;
      case MSG_COMPILE: {
        clear_event(event);
        if (edit->modified) {
          msgbox(MW_WARNING, MB_OK, "Please save your code first");
          return;
        };
        if (!compile(current_file, NULL, NULL)) msgbox(MW_ERROR, MB_OK, "Compile failed");
      }; break;
      case MSG_RUN: {
        l_text exefile = NULL;
        clear_event(event);
        if (edit->modified) {
          msgbox(MW_WARNING, MB_OK, "Please save your code first");
          return;
        };
        exefile = (l_text) compile(current_file, NULL, NULL);
        if (exefile) {
          if (!run_file(exefile)) seal_error(ERR_INFO, "Can't run program (%s)", exefile);
          free(exefile);
        };
      }; break;
      case MSG_ABOUT: {
        msgbox(MW_INFO, MB_OK, "BEdit 1.1 (C) 2001 Kostas Michalopoulos aka Bad Sector\n\n\
e-mail: michalopoylos@hotmail.com\n\
www: http://www.badseal.org/");
        clear_event(event);
      }; break;
    };
  };
}

static t_point app_min_size(p_view o)
{
  return point_assign(250, 200);
}

void app_init()
{
  p_menuview menu;
  t_rect r = rect_assign(0, 0, 450, 400);
  mainwin = appwin_init(malloc(sizeof(t_appwin)), r, "BEdit 1.1", WF_MINIMIZE|WF_MAXIMIZE, ap_id, &trans_ev);
  VIEW(mainwin)->align |= TX_ALIGN_CENTER;
  #ifdef Bad_Seal
#ifdef WANT_OLD_STUFF
  mainwin->icon16 = (BITMAP*)GET_DATA(dat, 0);
#else
{
              p_appwin_extension ext;
              if( OBJECT(mainwin)->find_extension && 
                  (ext=(p_appwin_extension)OBJECT(mainwin)->find_extension(OBJECT(mainwin), BS_APPWIN_NAME, BS_APPWIN_VERSION)))
                 ext->icon16= (BITMAP*)GET_DATA(dat, 0);
}
#endif
  mainwin->menu = standard_system_menu_items(mainwin,
               new_menu_line(
               new_menu_item("About BEdit...", 0, 0, MSG_ABOUT, NULL,
  NULL)));
#endif
  VIEW(mainwin)->size_minimum = &app_min_size;
  OBJECT(desktop)->insert(OBJECT(desktop), OBJECT(mainwin));
  r = rect_assign(2, 20, 448, 40);
  menu = hormenu_init(malloc(sizeof(t_menuview)), r, bedit_menu());
  OBJECT(mainwin)->insert(OBJECT(mainwin), OBJECT(menu));
  r = rect_assign(2, 45, 448, 383);
  edit = beditor_init(malloc(sizeof(t_beditor)), r, 0);
  VIEW(edit)->align |= TX_ALIGN_BOTTOM+TX_ALIGN_RIGHT;
  OBJECT(mainwin)->insert(OBJECT(mainwin), OBJECT(edit));
  r = rect_assign(2, 385, 448, 398);
  status = stattext_init(malloc(sizeof(t_stattext)), r, TX_ALIGN_LEFT,
      "Welcome to BEdit 1.1 by Bad Sector (K. Michalopoulos)");
  VIEW(status)->align |= TX_ALIGN_BOTTOM+TX_ALIGN_RIGHT;
  OBJECT(mainwin)->insert(OBJECT(mainwin), OBJECT(status));
}

app_begin(void)
{
  if (ap_process == AP_INIT) {
    l_text t;
    #ifdef Bad_Seal
    dat = conv_to_skipcolor_data(DLXGetFileData(ap_id), CO_SKIP_RED, CO_SKIP_GREEN, CO_SKIP_BLUE);
    #endif
    current_path = strdup("c:/");
    app_init();
    t = file_gettext(ap_args);
    if (t) {
      current_file = strdup(ap_args);
      edit->set_text(edit, t);
      redraw_title();
      free(t);
    };
  };
} app_end;

