#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <winlib/winlib.h>

#include "gshhs.h"

HINSTANCE hInst;
HWND hwndStatus;
int statusHeight;


BOOL DrawMap(HWND hwnd, HDC hdc)
{
       FILE *f;
       double w, e, s, n, area, lon, lat;
       char source;
       int     i;
       int max_east = 270000000;
       struct GSHHS h;
       struct GSHHS_POINT p;
       POINT *dPoints;
       RECT rect;
       HBRUSH hBrush;
       HPEN hPen;
       double xScaleFact, yScaleFact;
       BOOL retVal = TRUE;

       if (! (f = fopen("d:/Graphics/GIS/GSHHS/gshhs_l.b", "rb"))) {
               MBPrintf("DrawMap", "Error opening data file");
               return FALSE;
       }

       ShowStatus(hwndStatus, 0, "Processing...");

       GetClientRect(hwnd, &rect);

       xScaleFact = (double)rect.right / 360.0;
       yScaleFact = (300.0 * ((double)rect.right / 600.0)) / 180.0;

       rect.bottom -= statusHeight;
       hBrush = CreateSolidBrush(0x00ffd0d0);
       FillRect (hdc, &rect, hBrush);
       DeleteObject(hBrush);

       hBrush = CreateSolidBrush(0x00207020);
       hPen = CreatePen(PS_SOLID, 0, 0x00207020);
       SelectObject(hdc, (HGDIOBJ)hBrush);
       SelectObject(hdc, (HGDIOBJ)hPen);

       while (fread((void *)&h, (size_t)sizeof (struct GSHHS), (size_t)1, f) == 1) {
               h.id = swabi4 ((unsigned int)h.id);
               h.n = swabi4 ((unsigned int)h.n);
               h.level = swabi4 ((unsigned int)h.level);
               h.west = swabi4 ((unsigned int)h.west);
               h.east = swabi4 ((unsigned int)h.east);
               h.south = swabi4 ((unsigned int)h.south);
               h.north = swabi4 ((unsigned int)h.north);
               h.area = swabi4 ((unsigned int)h.area);
               h.greenwich = swabi2 ((unsigned int)h.greenwich);
               h.source = swabi2 ((unsigned int)h.source);
/*
               if (h.level != 1) {
                       for (i = 0; i < h.n; i++) {
                               if (fread ((void *)&p, (size_t)sizeof(struct GSHHS_POINT),
                                               (size_t)1, f) != 1) {
                                       MBPrintf("DrawMap", "Error reading file for polygon %d, point %d.\n", h.id, i);
                                       retVal = FALSE;
                                       goto end;
                               }
                       }
                       continue;
               }
*/
               w = h.west  * 1.0e-6;
               e = h.east  * 1.0e-6;
               s = h.south * 1.0e-6;
               n = h.north * 1.0e-6;
               source = (h.source == 1) ? 'W' : 'C';
               area = 0.1 * h.area;

               dPoints = (POINT *)malloc(sizeof(POINT) * h.n);

               for (i = 0; i < h.n; i++) {
                       if (fread ((void *)&p, (size_t)sizeof(struct GSHHS_POINT),
                                       (size_t)1, f) != 1) {
                               MBPrintf("DrawMap", "Error reading file for polygon %d, point %d.\n", h.id, i);
                               retVal = FALSE;
                               goto end;
                       }

                       p.x = swabi4 ((unsigned int)p.x);
                       p.y = swabi4 ((unsigned int)p.y);

                       lon = (h.greenwich && p.x > max_east) ?
                                       p.x * 1.0e-6 - 360.0 : p.x * 1.0e-6;

                       lat = p.y * 1.0e-6;

                       dPoints[i].x = (lon * xScaleFact);
                       dPoints[i].y = (rect.bottom / 2) - (lat * yScaleFact);
               }

               if (! Polygon(hdc, dPoints, h.n)) {
                       MBPrintf("DrawMap", "Polygon overflow: %d points", h.n);
                       retVal = FALSE;
                       goto end;
               }

               free(dPoints);
               max_east = 180000000;
       }

end:
       fclose(f);
       DeleteObject(hBrush);
       DeleteObject(hPen);
       ShowStatus(hwndStatus, 0, "Done");
       return retVal;
}


LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam,
               LPARAM lParam)
{
       HDC hdc;
       PAINTSTRUCT ps;
       RECT rect;
       int x, y;
       BOOL r;

       switch (msg) {
               case WM_CREATE:
                       hwndStatus = CreateStatusWnd(hInst, hwnd, 2);
                       GetWindowRect(hwndStatus, &rect);
                       statusHeight = rect.bottom - rect.top;

                       x = (int)(((LPCREATESTRUCT)lParam)->x);
                       y = (int)(((LPCREATESTRUCT)lParam)->y);
                       MoveWindow(hwnd, x, y,
                                       600 + (GetSystemMetrics(SM_CXSIZEFRAME) * 2),
                                       300 + statusHeight + GetSystemMetrics(SM_CYCAPTION) +
                                               (GetSystemMetrics(SM_CYSIZEFRAME) * 2),
                                       TRUE);
                       return 0;

               case WM_SIZE:
                       SendMessage(hwndStatus, WM_SIZE, wParam, lParam);
                       SetStatusParts(hwndStatus, 2);
                       return 0;

               case WM_PAINT:
                       hdc = BeginPaint(hwnd, &ps);
                       r = DrawMap(hwnd, hdc);
                       EndPaint(hwnd, &ps);
                       if (! r)
                               exit(1);
                       return 0;

               case WM_DESTROY:
                       PostQuitMessage(0);
                       return 0;
       }
       return DefWindowProc(hwnd,msg,wParam,lParam);
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
               LPSTR lpCmdLine, INT nCmdShow)
{
       WNDCLASS wc;
       HWND hwnd;
       MSG msg;

       hInst = hInstance;

       wc.style = CS_HREDRAW | CS_VREDRAW;
       wc.lpfnWndProc = (WNDPROC)MainWndProc;
       wc.cbClsExtra = 0;
       wc.cbWndExtra = 0;
       wc.hInstance = hInstance;
       wc.hIcon = LoadIcon(hInstance, IDI_WINLOGO);
       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
       wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
       wc.lpszMenuName = NULL;
       wc.lpszClassName = "MainWndClass";
       if (! RegisterClass(&wc))
               return 0;

       hwnd = CreateWindow(
               "MainWndClass",
               "DrawMap",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, 0, 600, 375,
               NULL, NULL, hInstance, NULL);

       ShowWindow(hwnd, nCmdShow);

       while (GetMessage (&msg, NULL, 0, 0)) {
               TranslateMessage(&msg);
               DispatchMessage(&msg);
       }

       return msg.wParam;
}