//
//  g++ -static -mwindows -o getBarLength.exe getBarLength.cpp
//  strip getBarLength.exe
//
#include <windows.h>
//#include <Shlwapi.h>
#include <stdio.h>
#include <tchar.h>

BOOL debug = false;

int capture(HWND hWnd, int x1, int y1, int x2, int y2){
	HDC hdc;
	static BITMAPINFO bmpInfo;
	static LPDWORD lpPixel;
	static HBITMAP hBitmap;
	static HDC hMemDC;
	int width, height;

	width  = x2 - x1 + 1;
	height = y2 - y1 + 1;

	bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmpInfo.bmiHeader.biWidth = width;
	bmpInfo.bmiHeader.biHeight = height;
	bmpInfo.bmiHeader.biPlanes = 1;
	bmpInfo.bmiHeader.biBitCount = 32;
	bmpInfo.bmiHeader.biCompression = BI_RGB;

	hdc = GetDC(hWnd);
	hBitmap = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, (void**)&lpPixel, NULL, 0);
	hMemDC = CreateCompatibleDC(hdc);
	SelectObject(hMemDC, hBitmap);
	ReleaseDC(hWnd, hdc);

	PrintWindow(hWnd, hMemDC, PW_CLIENTONLY);

	// 1小節のピクセル数を調べる
	int barLength = 0;
	int candKindNum = 0, candNum = 0;
	int candMax = 30;
	int *barLengthCand, *barLengthCandN;
	barLengthCand  = (int*) malloc(sizeof(int) * candMax);  // ピクセル数候補を保存する配列
	barLengthCandN = (int*) malloc(sizeof(int) * candMax);  // ピクセル数候補の出現回数を保存する配列
	for (int y = 40; y < height; y += 5){
		int x = 88;
		int i = y * width + x;
		if (lpPixel[i] != 0xff40ff && lpPixel[i] != 0x8080ff) continue;
		for (x = 88 + 1; x < width; x += 1){
			i = y * width + x;
			if (lpPixel[i] == 0xff40ff || lpPixel[i] == 0x8080ff) break;
			if (lpPixel[i] != 0x000000 && lpPixel[i] != 0xe0e0e0 && lpPixel[i] != 0xffffff) break;
			//fprintf(stderr, "(%d,%d) %x\n", x, y, lpPixel[y * width + x]);
		}
		if (x < width && (lpPixel[i] == 0xff40ff || lpPixel[i] == 0x8080ff)){
			barLength = x - 88;
			int c;
			for (c = 0; c < candKindNum; c++){
				if (barLengthCand[c] == barLength){	// 既に出現したことのある値なら出現数を増やす
					barLengthCandN[c]++;
					break;
				}
			}
			if (c >= candKindNum){					// 出現したことのない値の場合
				barLengthCand[candKindNum] = barLength;
				barLengthCandN[candKindNum] = 1;
				candKindNum++;
			}
			// fprintf(stderr, "x=%d, barLength= %d\n", x, barLength);
			candNum++;
			if (candNum >= candMax) break;
		}
	}
	int maxN = 0;
	for (int c = 1; c < candKindNum; c++){
		if (barLengthCandN[c] > barLengthCandN[maxN]) maxN = c;
	}
	barLength = barLengthCand[maxN];	// もっとも出現数の多かった値をbarLengthとして残す
	free(barLengthCand);
	free(barLengthCandN);

	// キャプチャした画像をファイル保存する場合
/*	HANDLE hFile = CreateFile(TEXT("result.bmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile != INVALID_HANDLE_VALUE){
		LONG lHeadSize  = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO);
		LONG lWidthSize = width * sizeof(DWORD);
		LONG lImageSize = lWidthSize * height;
		DWORD dwSize;

		// ヘッダ
		BITMAPFILEHEADER bmpHead = {0};
		bmpHead.bfType          = 0x4D42;       // 識別子(BM)
		bmpHead.bfSize          = lHeadSize + lImageSize;
		bmpHead.bfReserved1     = 0;
		bmpHead.bfReserved2     = 0;
		bmpHead.bfOffBits       = lHeadSize;

		// ファイル書き込み
		WriteFile(hFile, &bmpHead, sizeof(BITMAPFILEHEADER), &dwSize, NULL);
		WriteFile(hFile, &bmpInfo, sizeof(BITMAPINFO),       &dwSize, NULL);
		WriteFile(hFile, lpPixel,  lImageSize,               &dwSize, NULL);

		CloseHandle(hFile);
	}
	*/

	DeleteDC(hMemDC);
	DeleteObject(hBitmap);

	return barLength;
}

BOOL CALLBACK EnumWndProc(HWND hWnd, LPARAM lParam){
	char *buf;
	int len;
	len = GetWindowTextLength(hWnd);
	buf = (char*)malloc(sizeof(LPWSTR)*len + 2);
	GetWindowText(hWnd, buf, len);
	//wsprintfA(charbuf, sizeof(TCHAR)==2 ? "%S" : "%s", buf);
	//if(strstr((char*)charbuf, "- ＵＴＡＵ")!=NULL){
	//if (StrStrW(buf, TEXT("- ＵＴＡ"))!=NULL){
	if (strstr(buf, TEXT("- ＵＴＡ"))!=NULL){
		(*(HWND*)lParam) = hWnd;//ウィンドウハンドルを渡す
    if (debug){
      fprintf(stderr, "buf=%s\n", buf);
    }
	}
	return true;
}

//
// UTAUの一拍分のピクセル数を出力する
// 求まらない場合は0を出力する
//
int _tmain(int argc, _TCHAR* argv[]){
	HWND hWnd;
	RECT rc;
	int x1, y1, x2, y2, barLength = 0;
	hWnd =NULL;

	EnumWindows( EnumWndProc, (LPARAM)&hWnd);

	if(hWnd != NULL){
		GetClientRect(hWnd, &rc);
		x1 = rc.left;
		x2 = rc.right;
		y1 = rc.top;
		y2 = rc.bottom;
		barLength = capture(hWnd, x1, y1, x2, y2);
	}
	if (debug){
		fprintf(stderr, "barLength = %d\n", barLength);
		//getchar();
	}
	printf("%d", barLength);
	return 0;
}

