#if WIN32
#   define _MSC_VER 1
#	define _CRT_SECURE_NO_WARNINGS
#   include <Windows.h>
#else
#
#endif

#include <OpenDoor.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>

char **quote_lines;
int quote_line_count;

char *msgfrom;
char *msgto;
char *msgsubj;
char *msgarea;
int msgpriv;

char *message_editor() {
    char **body_lines;
    int body_line_count;
    int position_x;
    int position_y;
    int done;
    char line[81];
    char line_cpy[81];
    int top_of_screen = 0;
    int i, j;
    char *return_body;
    int body_len;
    tODInputEvent ch;
    int q_done;
    char q_marker;
    int q_start;
    int q_position;
    int *q_lines;
    int q_line_count;
    int q_unquote;
    int z;

    position_x = 0;
    position_y = 0;

    body_line_count = 0;
    done = 0;

    memset(line, 0, 81);
    memset(line_cpy, 0, 81);

    while (!done) {
        od_clr_scr();
        od_set_cursor(1, 1);
        od_set_color(L_WHITE, D_BLUE);
        od_printf("  TO: %-32.32s AREA: %-32.32s", msgto, msgarea);
        od_clr_line();
        od_set_cursor(2, 1);
        od_printf("SUBJ: %s", msgsubj);
        od_clr_line();
        od_set_cursor(24, 1);
        od_printf("Enter /S to save, /Q to quote or /A to abort on a new line.");
        od_clr_line();
        od_set_cursor(3, 1);
        od_set_color(L_WHITE, D_BLACK);
        while (1) {
            od_get_input(&ch, OD_NO_TIMEOUT, GETIN_NORMAL);
            if (ch.EventType == EVENT_EXTENDED_KEY) {
                if (ch.chKeyPress == OD_KEY_UP) {
                    if (position_y > 0) {
                        strcpy(line_cpy, body_lines[position_y - 1]);
                        free(body_lines[position_y - 1]);
                        body_lines[position_y - 1] = strdup(line);
                        strcpy(line, line_cpy);
                        position_y--;

                        if (position_x >= strlen(line)) {
                            position_x = strlen(line);
                        }

                        if (position_y < top_of_screen) {
                            top_of_screen--;

                        }
                        od_set_cursor(3, 1);

                        for (i=top_of_screen;i<position_y;i++) {
                            od_set_cursor(i - top_of_screen + 3, 1);
                            od_printf("%s", body_lines[i]);
                            od_clr_line();
                        }
                        od_set_cursor(i - top_of_screen + 3, 1);
                        od_printf("%s", line);
                        od_clr_line();
                        for (i=position_y;i<body_line_count && i < top_of_screen + 20;i++) {
                            od_set_cursor(i - top_of_screen + 4, 1);
                            od_printf("%s", body_lines[i]);
                            od_clr_line();
                        }



                        od_set_cursor(position_y - top_of_screen + 3, position_x + 1);
                    }
                } else if (ch.chKeyPress == OD_KEY_DOWN) {
                    if (position_y < body_line_count) {
                        strcpy(line_cpy, body_lines[position_y]);
                        free(body_lines[position_y]);
                        body_lines[position_y] = strdup(line);
                        strcpy(line, line_cpy);
                        position_y++;

                        if (position_x >= strlen(line)) {
                            position_x = strlen(line);
                        }

                        if (position_y > top_of_screen + 20) {
                            top_of_screen++;

                        }
                        od_set_cursor(3, 1);

                        for (i=top_of_screen;i<position_y;i++) {
                            od_set_cursor(i - top_of_screen + 3, 1);
                            od_printf("%s", body_lines[i]);
                            od_clr_line();
                        }
                        od_set_cursor(i - top_of_screen + 3, 1);
                        od_printf("%s", line);
                        od_clr_line();
                        for (i=position_y;i<body_line_count && i < top_of_screen + 20;i++) {
                            od_set_cursor(i - top_of_screen + 4, 1);
                            od_printf("%s", body_lines[i]);
                            od_clr_line();
                        }

                        od_set_cursor(position_y - top_of_screen + 3, position_x + 1);
                    }
                } else if (ch.chKeyPress == OD_KEY_LEFT) {
                    if (position_x > 0) {
                        position_x--;
                        od_set_cursor(position_y - top_of_screen + 3, position_x + 1);
                    }

                } else if (ch.chKeyPress == OD_KEY_RIGHT) {
                    if (position_x < strlen(line)) {
                        position_x++;
                        od_set_cursor(position_y - top_of_screen + 3, position_x + 1);
                    }
                }
            } else if (ch.EventType == EVENT_CHARACTER) {
                if (ch.chKeyPress == '\r' || strlen(line) >= 73) {
                    if (strcasecmp(line, "/S") == 0) {
                        // save message
                        body_len = 0;
                        for (i=0;i<body_line_count;i++) {
                                body_len = body_len + strlen(body_lines[i]) + 2;
                        }
                        body_len++;

                        return_body = (char *)malloc(body_len);
                        memset(return_body, 0, body_len);

                        for (i=0;i<body_line_count;i++) {
                                strcat(return_body, body_lines[i]);
                                strcat(return_body, "\r\n");
                        }
                        if (body_line_count > 0) {
                            for (i=0;i<body_line_count;i++) {
                                free(body_lines[i]);
                            }
                            free(body_lines);
                        }

                        return return_body;
                    } else if (strcasecmp(line, "/A") == 0) {
                        // abort message
                        if (body_line_count > 0) {
                            for (i=0;i<body_line_count;i++) {
                                free(body_lines[i]);
                            }
                            free(body_lines);
                        }
                        return NULL;
                    } else if (strcasecmp(line, "/Q") == 0) {
                        // quote
                        if (quote_line_count > 0) {
                            od_clr_scr();
                            od_set_cursor(1, 1);
                            od_set_color(L_WHITE, D_BLUE);
                            od_printf("Quoting Message --");
                            od_clr_line();
                            od_set_cursor(2, 1);
                            od_printf("Press Enter to Select a line, Q to Quote, A to Abort");
                            od_clr_line();
                            od_set_cursor(3, 1);
                            od_set_color(L_WHITE, D_BLACK);

                            q_start = 0;
                            q_position = 0;
                            q_line_count = 0;
                            q_done = 0;
                            q_marker = ' ';
                            while (!q_done) {
                                for (i=q_start;i<q_start + 21 && i < quote_line_count;i++) {
                                    q_marker = ' ';
                                    for (j=0;j<q_line_count;j++) {
                                        if (q_lines[j] == i) {
                                            q_marker = '+';
                                            break;
                                        }
                                    }
                                    od_set_cursor(i - q_start + 3, 1);
                                    if (i == q_position) {
                                       od_set_color(D_BLACK, D_GREEN);
                                       od_printf("`bright yellow`%c`black green`%s", q_marker, quote_lines[i]);
                                       od_clr_line();
                                    } else {
                                       od_set_color(L_WHITE, D_BLACK);
                                       od_printf("`bright yellow`%c`bright white`%s", q_marker, quote_lines[i]);
                                       od_clr_line();
                                    }
                                }
                                od_get_input(&ch, OD_NO_TIMEOUT, GETIN_NORMAL);
                                if (ch.EventType == EVENT_EXTENDED_KEY) {
                                    if (ch.chKeyPress == OD_KEY_UP) {
                                        q_position--;
                                        if (q_position < 0) {
                                            q_position = 0;
                                        }
                                        if (q_position < q_start) {
                                            q_start = q_start - 21;
                                            if (q_start < 0) {
                                                q_start = 0;
                                            }
                                        }
                                    } else if (ch.chKeyPress == OD_KEY_DOWN) {
                                        q_position++;
                                        if (q_position >= quote_line_count) {
                                            q_position = quote_line_count - 1;
                                        }

                                        if (q_position >= q_start + 21) {
                                            q_start = q_start + 21;
                                            if (q_start + 21 >= quote_line_count) {
                                                q_start = quote_line_count - 21;
                                            }
                                        }
                                    }
                                } else if (ch.EventType == EVENT_CHARACTER) {
                                    if (ch.chKeyPress == 13) {
                                        q_unquote = 0;
                                        if (q_line_count > 0) {
                                            for (i=0;i<q_line_count;i++) {
                                                if (q_lines[i] == q_position) {
                                                    for (j=i;j<q_line_count-1;j--) {
                                                        q_lines[j] = q_lines[j + 1];
                                                    }
                                                    q_line_count--;
                                                    if (q_line_count == 0) {
                                                        free(q_lines);
                                                    } else {
                                                        q_lines = realloc(q_lines, q_line_count * sizeof(int));
                                                    }
                                                    q_unquote = 1;
                                                    break;
                                                }
                                            }
                                        }
                                        if (!q_unquote) {
                                            if (q_line_count == 0) {
                                                q_lines = (int *)malloc(sizeof(int *));
                                            } else {
                                                q_lines = (int *)realloc(q_lines, sizeof(int *) * (q_line_count + 1));
                                            }

                                            q_lines[q_line_count] = q_position;
                                            q_line_count++;
                                        }
                                    } else if (tolower(ch.chKeyPress) == 'q') {
                                        for (i=0;i<q_line_count;i++) {
                                            if (body_line_count == 0) {
                                                body_lines = (char **)malloc(sizeof(char *));
                                            } else {
                                                body_lines = (char **)realloc(body_lines, sizeof(char *) * (body_line_count + 1));
                                            }
                                            body_lines[body_line_count] = strdup(quote_lines[q_lines[i]]);
                                            body_line_count++;

                                            position_y++;
                                        }
                                        if (q_line_count) {
                                            free(q_lines);
                                        }
                                        position_x = 0;
                                        q_done = 1;
                                    } else if (tolower(ch.chKeyPress) == 'a') {
                                        if (q_line_count) {
                                            free(q_lines);
                                        }
                                        q_done = 1;
                                    }
                                }

                            }

                        }
                        // restore screen
                        od_set_color(L_WHITE, D_BLACK);
                        od_clr_scr();
                        od_set_cursor(1, 1);
                        od_set_color(L_WHITE, D_BLUE);
                        od_printf("  TO: %-32.32s AREA: %-32.32s", msgto, msgarea);
                        od_clr_line();
                        od_set_cursor(2, 1);
                        od_printf("SUBJ: %s", msgsubj);
                        od_clr_line();
                        od_set_cursor(24, 1);
                        od_printf("Enter /S to save, /Q to quote or /A to abort on a new line.");
                        od_clr_line();
                        od_set_cursor(3, 1);
                        od_set_color(L_WHITE, D_BLACK);

                        for (i=top_of_screen;i<top_of_screen + 20;i++) {
                            od_set_cursor(i - top_of_screen + 3, 1);
                            if (i < body_line_count) {
                                od_printf("%s", body_lines[i]);
                            }
                            od_clr_line();
                        }
                        position_x = 0;
                        memset(line, 0, 81);
                        od_set_cursor(position_y - top_of_screen + 3, position_x + 1);
                    } else {
                        if (strlen(line) >= 73) {
                            if (position_x == strlen(line)) {
                                strncat(line, &ch.chKeyPress, 1);
                                z = 1;
                            } else {
                                strncpy(line_cpy, line, position_x);
                                line_cpy[position_x] = '\0';
                                strncat(line_cpy, &ch.chKeyPress, 1);
                                strcat(line_cpy, &line[position_x]);
                                memset(line, 0, 81);
                                strcpy(line, line_cpy);
                                memset(line_cpy, 0, 81);
                                z = 0;
                            }

                            for (i=strlen(line)-1;i>0;i--) {
                                if (line[i] == ' ') {
                                    line[i] = '\0';
                                    strcpy(line_cpy, &line[i+1]);
                                    if (body_line_count == 0) {
                                        body_lines = (char **)malloc(sizeof(char *));
                                    } else {
                                        body_lines = (char **)realloc(body_lines, sizeof(char *) * (body_line_count + 1));
                                    }
                                    if (z == 1) {
                                        for (j=body_line_count;j>position_y;j--) {
                                            body_lines[j] = body_lines[j-1];
                                        }
                                        body_line_count++;
                                        body_lines[j] = strdup(line);

                                        position_y++;
                                        if (position_y - top_of_screen > 20) {
                                            top_of_screen++;
                                        }

                                        strcpy(line, line_cpy);
                                        memset(line_cpy, 0, 81);
                                        position_x = strlen(line);
                                    } else {
                                        if (strlen(body_lines[position_y]) + strlen(line_cpy) + 1 <= 73) {
                                            strcat(line_cpy, " ");
                                            strcat(line_cpy, body_lines[position_y]);
                                            free(body_lines[position_y]);
                                            body_lines[position_y] = strdup(line_cpy);
                                            memset(line_cpy, 0, 81);
                                            position_x++;
                                        } else {
                                            for (j=body_line_count;j>position_y;j--) {
                                                body_lines[j] = body_lines[j-1];
                                            }
                                            body_line_count++;
                                            body_lines[j] = strdup(line_cpy);

                                            memset(line_cpy, 0, 81);
                                            position_x++;
                                        }
                                    }
                                    break;
                                }
                            }
                            if (i==0) {
                                position_x++;
                                if (body_line_count == 0) {
                                    body_lines = (char **)malloc(sizeof(char *));
                                } else {
                                    body_lines = (char **)realloc(body_lines, sizeof(char *) * (body_line_count + 1));
                                }

                                for (i=body_line_count;i>position_y;i--) {
                                    body_lines[i] = body_lines[i-1];
                                }
                                body_line_count++;
                                body_lines[i] = strdup(line);
                                if (z == 1) {
                                    position_y++;
                                    if (position_y - top_of_screen > 20) {
                                        top_of_screen++;
                                    }
                                    position_x = 0;
                                }
                                memset(line, 0, 81);
                            }
                        } else {

                            if (position_x < strlen(line)) {
                                // insert line
                                if (body_line_count == 0) {
                                    body_lines = (char **)malloc(sizeof(char *));
                                } else {
                                    body_lines = (char **)realloc(body_lines, sizeof(char *) * (body_line_count + 1));
                                }

                                for (i=body_line_count;i>position_y;i--) {
                                    body_lines[i] = body_lines[i-1];
                                }

                                body_line_count++;
                                body_lines[i] = (char *)malloc(sizeof(char) * (position_x + 1));
                                strncpy(body_lines[i], line, position_x);
                                body_lines[i][position_x] = '\0';
                                strcpy(line_cpy, &line[position_x]);
                                memset(line, 0, 81);
                                strcpy(line, line_cpy);
                                memset(line_cpy, 0, 81);

                                position_y++;
                                if (position_y - top_of_screen > 20) {
                                    top_of_screen++;
                                }

                            } else {
                                if (body_line_count == 0) {
                                    body_lines = (char **)malloc(sizeof(char *));
                                } else {
                                    body_lines = (char **)realloc(body_lines, sizeof(char *) * (body_line_count + 1));
                                }

                                for (i=body_line_count;i>position_y;i--) {
                                    body_lines[i] = body_lines[i-1];
                                }
                                body_line_count++;
                                body_lines[i] = strdup(line);

                                position_y++;
                                if (position_y - top_of_screen > 20) {
                                    top_of_screen++;
                                }
                                position_x = 0;
                                memset(line, 0, 81);
                            }
                        }


                        od_set_cursor(3, 1);

                        for (i=top_of_screen;i<position_y;i++) {
                            od_set_cursor(i - top_of_screen + 3, 1);
                            od_printf("%s", body_lines[i]);
                            od_clr_line();
                        }
                        od_set_cursor(i - top_of_screen + 3, 1);
                        od_printf("%s", line);
                        od_clr_line();
                        for (i=position_y;i<body_line_count && i - top_of_screen < 20;i++) {
                            od_set_cursor(i - top_of_screen + 4, 1);
                            od_printf("%s", body_lines[i]);
                            od_clr_line();
                        }

                        od_set_cursor(position_y - top_of_screen + 3, position_x + 1);
                    }
                } else {
                    if (ch.chKeyPress == '\b') {
                        if (position_x == 0) {
                            // TODO
                        } else {
                            if (position_x >= strlen(line)) {
                                strncpy(line_cpy, line, strlen(line) - 1);
                                line_cpy[strlen(line) - 1] = '\0';
                                memset(line, 0, 81);
                                strcpy(line, line_cpy);
                                memset(line_cpy, 0, 81);
                                position_x--;
                            } else {
                                strncpy(line_cpy, line, position_x -1);
                                line_cpy[position_x - 1] = '\0';
                                strcat(line_cpy, &line[position_x]);
                                strcpy(line, line_cpy);
                                memset(line_cpy, 0, 81);
                                position_x--;

                            }
                        }
                    } else if (ch.chKeyPress != '\n') {
                        if (position_x >= strlen(line)) {
                            strncat(line, &ch.chKeyPress, 1);
                        } else {
                            strncpy(line_cpy, line, position_x);
                            line_cpy[position_x] = '\0';
                            strncat(line_cpy, &ch.chKeyPress, 1);
                            strcat(line_cpy, &line[position_x]);
                            memset(line, 0, 81);
                            strcpy(line, line_cpy);
                            memset(line_cpy, 0, 81);
                        }
                        position_x++;

                    }

                    if (position_y > 20) {
                        od_set_cursor(23, 1);
                        od_clr_line();
                    } else {
                        od_set_cursor(position_y + 3, 1);
                        od_clr_line();
                    }

                    for (i = 0; i < position_x; i++) {
                        od_printf("%c", line[i]);
                    }

                    if (position_x < strlen(line) ) {
                        for (i = position_x; i < strlen(line); i++) {
                            od_printf("%c", line[i]);
                        }
                    }

					if (position_y > 20) {
                        od_set_cursor(23, position_x + 1);
					} else {
					    od_set_cursor(position_y - top_of_screen + 3, position_x + 1);
                    }
                }
            }
        }
    }
}

#if _MSC_VER
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
#else
int main(int argc, char **argv)
{
#endif
    char *msgtmp;
    char *msginf;
    char path_sep;
    char *msgpath;
    int noquote;
    char buffer[256];
    FILE *fptr;
    char *body;
    int i;
#if _MSC_VER
    int j;

	for (i=0;i<strlen(lpszCmdLine);i++) {
        if (strncmp(&lpszCmdLine[i], "-MSGTMP ", 8) == 0 || strncmp(&lpszCmdLine[i], "/MSGTMP ", 8) == 0) {
            msgpath = strdup(&lpszCmdLine[i + 8]);
            for (j=0;j<strlen(msgtmp);j++) {
                if (msgpath[j] == ' ') {
                    msgpath[j] = '\0';
                    break;
                }
            }
        }
	}
    od_parse_cmd_line(lpszCmdLine);
    path_sep = '\';'
#else
	for (i=0;i<argc;i++) {
		if (strcmp(argv[i], "-MSGTMP") == 0 || strcmp(argv[i], "/MSGTMP") == 0) {

			msgpath = strdup(argv[i+1]);
		}
	}
    od_parse_cmd_line(argc, argv);
    path_sep = '/';
#endif

    od_init();

    msgtmp = (char *)malloc(strlen(msgpath) + 8);
    if (!msgtmp) {
        od_printf("Out of Memory!\r\n");
        od_exit(-1, FALSE);
    }

    msginf = (char *)malloc(strlen(msgpath) + 8);
    if (!msginf) {
        od_printf("Out of Memory!\r\n");
        od_exit(-1, FALSE);
    }

    sprintf(msgtmp, "%s%cMSGTMP", msgpath, path_sep);
    sprintf(msginf, "%s%cMSGINF", msgpath, path_sep);


    fptr = fopen(msginf, "r");

    if (!fptr) {
        sprintf(msginf, "%s%cmsginf", msgpath, path_sep);
        fptr = fopen(msginf, "r");
        if (!fptr) {
            od_printf("Unable to open MSGINF!\r\n");
            od_exit(-1, FALSE);
            return -1;
        }
    }

    fgets(buffer, 256, fptr);
    for (i=strlen(buffer) - 1; i > 0; i--) {
        if (buffer[i] != '\r' && buffer[i] != '\n') {
            break;
        } else {
            buffer[i] = '\0';
        }
    }

    msgfrom = strdup(buffer);

    fgets(buffer, 256, fptr);
    for (i=strlen(buffer) - 1; i > 0; i--) {
        if (buffer[i] != '\r' && buffer[i] != '\n') {
            break;
        } else {
            buffer[i] = '\0';
        }
    }

    msgto = strdup(buffer);

    fgets(buffer, 256, fptr);
    for (i=strlen(buffer) - 1; i > 0; i--) {
        if (buffer[i] != '\r' && buffer[i] != '\n') {
            break;
        } else {
            buffer[i] = '\0';
        }
    }

    msgsubj = strdup(buffer);

    fgets(buffer, 256, fptr); // msg no, we don't care

    fgets(buffer, 256, fptr);
    for (i=strlen(buffer) - 1; i > 0; i--) {
        if (buffer[i] != '\r' && buffer[i] != '\n') {
            break;
        } else {
            buffer[i] = '\0';
        }
    }

    msgarea = strdup(buffer);

    fgets(buffer, 256, fptr);
    for (i=strlen(buffer) - 1; i > 0; i--) {
        if (buffer[i] != '\r' && buffer[i] != '\n') {
            break;
        } else {
            buffer[i] = '\0';
        }
    }

    if (strcasecmp(buffer, "YES") == 0) {
        msgpriv = 1;
    } else {
        msgpriv = 0;
    }


    fclose(fptr);

    noquote = 0;

    fptr = fopen(msgtmp, "r");

    if (!fptr) {
        sprintf(msgtmp, "%s%cmsgtmp", msgpath, path_sep);
        fptr = fopen(msgtmp, "r");
        if (!fptr) {
            sprintf(msgtmp, "%s%cMSGTMP", msgpath, path_sep);
            noquote = 1;
        }
    }
    quote_line_count = 0;
    if (!noquote) {
        fgets(buffer, 73, fptr);
        while (!feof(fptr)) {
            for (i=strlen(buffer) - 1; i >= 0; i--) {
                if (buffer[i] != '\r' && buffer[i] != '\n') {
                    break;
                } else {
                    buffer[i] = '\0';
                }
            }

            if (quote_line_count == 0) {
                quote_lines = (char **)malloc(sizeof(char *));
            } else {
                quote_lines = (char **)realloc(quote_lines, sizeof(char *) * (quote_line_count + 1));
            }

            quote_lines[quote_line_count] = (char *)malloc(strlen(buffer) + 5);

            sprintf(quote_lines[quote_line_count], " %c> %s", msgto[0], buffer);

            quote_line_count++;

            fgets(buffer, 73, fptr);
        }
        fclose(fptr);
        unlink(msgtmp);
    }

    body = message_editor();

    if (body == NULL) {
        od_printf("Message Aborted!\r\n");
        od_exit(0, FALSE);
        return 0;
    }

    for (i=0;i<quote_line_count;i++) {
        free(quote_lines[i]);
    }

    free(quote_lines);

    fptr = fopen(msgtmp, "w");

    if (!fptr) {
        od_printf("Error saving message!\r\n");
        od_exit(-1, FALSE);
        return -1;
    }

    fwrite(body, 1, strlen(body), fptr);

    fclose(fptr);

    od_exit(0, FALSE);
    return 0;
}