// for celestial navigation with a sextant and the Nautical Almanac
// SightReduction.rc and SightReduction.h (rename to resource.h) can be downloaded here: http:\\jdmcox.com\SightReduction.h
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include "resource.h"
#define PI 3.141592653589793

DWORD Width, Height;
double rad2deg = 180.0/PI, deg2rad = PI/180.0;
double Lat, LatDeg, LatMin, LatRad, Lon, LonDeg, LonMin, Dec, DecDeg, DecMin, DecRad, GHA, GHADeg, GHAMin, GHARad;
double LHA, LHARad, Hc, HcDeg, HcMin, HcRad, Z, ZDeg, ZMin, ZRad, Denominator;
char szAppName[] = "Sight Reduction Calculator";
char String[20];
HWND hwnd, hwndDlg;
HINSTANCE hInst;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	MSG          msg;
	WNDCLASS     wndclass;
	wndclass.style         = CS_HREDRAW|CS_VREDRAW;
	wndclass.lpfnWndProc   = WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = hInst;
	wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = szAppName;
	if (!RegisterClass(&wndclass))
		return 0;
	hwnd = CreateWindow(szAppName, szAppName,
		WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU,
		0, 0, 550, 390, // to completely ovelay DialogBox
		NULL, NULL, hInstance, NULL);
	ShowWindow(hwnd, SW_SHOWNORMAL);
	UpdateWindow(hwnd);
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_CREATE) {
		Width = GetSystemMetrics(SM_CXFULLSCREEN);
		Height = GetSystemMetrics(SM_CYFULLSCREEN);
		MoveWindow(hwnd, (Width/2)-212, (Height/2)-162, 425, 325, FALSE); // 425/2=212.5	325/2=162.5
		///////
		hwndDlg = CreateDialog(hInst, "DIALOG", hwnd, (DLGPROC)DialogProc);
		///////
		SetFocus(hwndDlg);
	}
	else if (message == WM_DESTROY)
		PostQuitMessage(0);
	return DefWindowProc(hwnd, message, wParam, lParam);
}

int CALLBACK DialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	if ((message == WM_COMMAND) && (LOWORD(wParam) == IDC_BUTTON1)) { // SIGHT REDUCTION CALCULATION
		GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT1), String, 10);
		GHADeg = atof(String);
		GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT2), String, 10);
		GHAMin = atof(String);
		GHA = GHADeg + (GHAMin/60.0);
		GHARad = deg2rad*GHA; // for trig functions
		GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT3), String, 10);
		DecDeg = atof(String);
		GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT4), String, 10);
		DecMin = atof(String);
		Dec = DecDeg + (DecMin/60.0);
		if (BST_CHECKED == IsDlgButtonChecked(hwndDlg, IDC_CHECK2)) // South Declination
			Dec = -Dec;
		DecRad = deg2rad*Dec;
		GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT5), String, 10);
		LonDeg = atof(String);
		GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT6), String, 10);
		LonMin = atof(String);
		Lon = LonDeg + (LonMin/60.0);
		if (BST_CHECKED == IsDlgButtonChecked(hwndDlg, IDC_CHECK1)) // West Longitude
			Lon = -Lon;
		GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT7), String, 10);
		LatDeg = atof(String);
		GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT8), String, 10);
		LatMin = atof(String);
		Lat = LatDeg + (LatMin/60.0);
		if (BST_CHECKED == IsDlgButtonChecked(hwndDlg, IDC_CHECK3)) // South Latitude
			Lat = -Lat;
		LatRad = deg2rad*Lat;
		LHA = GHA + Lon; // Lon is either +Lon or -Lon
		if (LHA > 360.0) LHA -= 360.0;
		else if (LHA < 0.0) LHA += 360.0;
		LHARad = deg2rad*LHA;
		HcRad = asin((sin(LatRad) * sin(DecRad)) + (cos(LatRad) * cos(DecRad) * cos(LHARad)));
		Hc = rad2deg*HcRad;
		HcMin = modf(Hc, &HcDeg);
		HcMin *= 60.0;
		_snprintf_s(String, 20, 20, ("%.0f"), HcDeg); // angle between horizon and celestial body
		SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT9), String);
		_snprintf_s(String, 20, 20, ("%.1f"), HcMin);
		SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT10), String);
//		if (Hc >= 0.0) { // from https://www.celnav.de/ (Astro.pdf)
			Denominator = ((sin(LatRad) * cos(LHARad)) - (tan(DecRad) * cos(LatRad)));
//			if (Denominator == 0.0)
//				goto bad;
			ZRad = atan(sin(LHARad) / Denominator); // Time Azimuth method
			Z = rad2deg*ZRad;
			if ((LHA < 180.0) && (Denominator < 0.0))
				Z += 360.0;
			else if (Denominator > 0.0)
				Z += 180.0;
			ZMin = modf(Z, &ZDeg);
			ZMin *= 60.0;
			_snprintf_s(String, 20, 20, ("%.0f"), ZDeg); // true compass bearing of celestial body
			SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT11), String);
			_snprintf_s(String, 20, 20, ("%.1f"), ZMin);
			SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT12), String);
//		}
//		else {
//bad:		MessageBox(hwndDlg, "Maybe it's below the horizon", "", MB_OK);
//			String[0] = 0;
//			SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT9), String);
//			SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT10), String);
//			SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT11), String);
//			SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT12), String);
//		}
	} // end of if ((message == WM_COMMAND)...
	return 0;
}
//			these also work:
//			ZRad2 = acos((sin(DecRad) - (sin(HcRad) * sin(LatRad))) / (cos(HcRad) * cos(LatRad))); // Altitude Azimuth
//			Z2 = rad2deg*ZRad2;
//			if (LHA < 180.0)
//				Z2 = 360.0 - Z2;
//			ZRad3 = acos(((cos(LatRad) * sin(DecRad)) - ((sin(LatRad) * cos(DecRad) * cos(LHARad)))) / cos(HcRad)); // Time-Altitude Azimuth
//			Z3 = rad2deg*ZRad3;
//			if (LHA < 180.0)
//				Z3 = 360 - Z3;
