/**
 * Windows 95 Keygen (Windows GUI ver.)
 * Copyright (c) Paper 2022
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
**/
#include <stdio.h>
#include <windows.h>
#include <stdint.h>
#include <stdbool.h>
#include <commdlg.h>
#include <math.h>
#include <time.h>
#include <bass.h>
#include <resource.h>
#define _WIN32_WINNT 0x0400
#define ARRAYSIZE(a) \
	sizeof(a)/sizeof(a[0])
#define CONCAT_INTS(x, y) \
	x * pow(10, log10(y)+1) + y
#ifdef _MSC_VER
#define strdup(p) _strdup(p)
#endif
#define GENERATE_KEY 1
#define LISTBOX      2
#define KEY          3
int type;
HWND hWndListBox, key_box;
HMUSIC music;

extern char binary_src_bergsm_xm_start[];
extern char binary_src_bergsm_xm_end[];

int get_sum(int n) {
	int sum;
	for (sum = 0; n > 0; sum += n % 10, n /= 10); // copied this from google. sorry not sorry
	return sum;
}

int win95_nt4_prefix() {
    int num = rand() % 999;
    while ((num == 333) || (num == 444) || (num == 555) || (num == 666) || (num == 777) || (num == 888) || (num == 999)) {
        num = num + 1;
    }
    return num;
}

int win95_suffix(bool is_oem) {
    int first_digits, last_digit, second_segment = 5;
    while (get_sum(second_segment) % 7 != 0) {
		if (is_oem == false) {
			first_digits = rand() % 999999;
		} else {
			first_digits = rand() % 9999;
		}
        last_digit = rand() % 9;
        while ((last_digit == 0) || (last_digit >= 8)) {
            last_digit = rand() % 9;
        }
		second_segment = CONCAT_INTS(first_digits, last_digit);
    }
    return second_segment;
}

int office_prefix() {
	int new_site = 0;
	int ez_pwned = 0;
	while (CONCAT_INTS(new_site, ez_pwned) == 0) {
		new_site = rand() % 99;
		ez_pwned = (new_site % 10) + 2;
		if (ez_pwned >= 10) {
			ez_pwned -= 10;
		}
	}
    return CONCAT_INTS(new_site, ez_pwned);
}

int oem_prefix() {
    const char* years[] = {
        "95",
        "96",
        "97",
        "98",
        "99",
        "00",
        "01",
        "02",
        "03"
    };
	char buf[6];
	sprintf(buf, "%03d", (rand() % 366) + 1);
	strcat(buf, years[rand() % 9]);
	int buf2 = atoi(buf);
    return buf2;
}

void AddControls(HWND hWnd) {
	int i = 0;
	/* Open File */
	HWND gen_button = CreateWindowA("Button", "Generate Key", WS_VISIBLE | WS_CHILD, (int)((225 - 100)/2), 5, 100, 20, hWnd, (HMENU)GENERATE_KEY, NULL, NULL);
	/* Type */
	TCHAR listbox_items[][22] = {"Windows 95 / NT 4 RTM", "Windows 95 OEM", "Office 97"};
	hWndListBox = CreateWindowA("Listbox", NULL, WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY, (int)((225 - 150)/2), 30, 150, 60, hWnd, (HMENU)LISTBOX, NULL, NULL);
	for (i = 0; i < ARRAYSIZE(listbox_items); i++) {
		int pos = (int)SendMessage(hWndListBox, LB_ADDSTRING, i, (LPARAM) listbox_items[i]);
		SendMessage(hWndListBox, LB_SETITEMDATA, pos, (LPARAM) i);
	}
	SendMessage(hWndListBox, LB_SETCURSEL, (WPARAM)0, (LPARAM)0);
	// idk
	key_box = CreateWindowA("Edit", "", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY | ES_CENTER | ES_MULTILINE | SS_CENTER, (int)((225 - 150)/2), 100, 150, 40, hWnd, (HMENU)KEY, NULL, NULL);
	if (gen_button == NULL || hWndListBox == NULL || key_box == NULL)
		MessageBoxA(hWnd, "how did you even trigger this", "GUI could not be initialized!", MB_ICONEXCLAMATION); 
}

bool CALLBACK SetFont(HWND child, LPARAM font) {
	SendMessage(child, WM_SETFONT, font, true);
	return true;
}

LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) {
	switch(msg) {
		case WM_COMMAND:
			if(HIWORD(wParam) == CBN_SELCHANGE) {
				if (LOWORD(wParam) == LISTBOX)
					type = SendMessageA((HWND) lParam, (UINT) LB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
			}
			switch(wParam) {
				case GENERATE_KEY: {
					char* p = calloc(24, sizeof(char));
					switch(type) {
						case 0:
							snprintf(p, 24, "%04d-%07d", office_prefix(), win95_suffix(false));
							SendMessageA(key_box, WM_SETTEXT, (WPARAM)0, (LPARAM)p);
							break;
						case 2:
							snprintf(p, 24, "%05d-OEM-%07d-%05d", oem_prefix(), win95_suffix(true), (rand() % 100000));
							SendMessageA(key_box, WM_SETTEXT, (WPARAM)0, (LPARAM)p);
							break;
						case 1:
							snprintf(p, 24, "%03d-%07d", win95_nt4_prefix(), win95_suffix(false));
							SendMessageA(key_box, WM_SETTEXT, (WPARAM)0, (LPARAM)p);
							break;
					}
				}
				case LISTBOX:
					break;
				case KEY:
					break;
			}
			break;
		case WM_CREATE: {
			if (!BASS_Init(-1, 48000, 0, hWnd, NULL)) {
				EndDialog(hWnd, 0);
				break;
			}
			AddControls(hWnd);
			EnumChildWindows(hWnd, (WNDENUMPROC)SetFont, (LPARAM)GetStockObject(DEFAULT_GUI_FONT));
			music = BASS_MusicLoad(true, &binary_src_bergsm_xm_start, 0, (unsigned int)(binary_src_bergsm_xm_end - binary_src_bergsm_xm_start), BASS_SAMPLE_LOOP | BASS_MUSIC_FT2PAN | BASS_MUSIC_NONINTER | BASS_SAMPLE_FLOAT, 1);
			BASS_ChannelPlay(music, FALSE);
			break;
		}
		case WM_DESTROY:
			BASS_MusicFree(music);
			BASS_Free();
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProcA(hWnd, msg, wParam, lParam);
	}
	return false;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR args, int ncmdshow) {
	srand((unsigned) time(NULL)); // magic rand() stuff :p
	WNDCLASSA wc = {0};

	wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hInstance = hInstance;
	wc.lpszClassName = "win95kg";
	wc.lpfnWndProc = WindowProcedure;
	wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(PEED));

	if (!RegisterClassA(&wc)) return -1;

	CreateWindowA("win95kg", "Windows 95 Keygen", WS_OVERLAPPED | WS_VISIBLE | WS_MINIMIZEBOX | WS_SYSMENU, 100, 100, 225, 200, NULL, NULL, hInstance, NULL);

	MSG msg = {0};

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