// Automatic Fever Screening.cpp : Defines the entry point for the application.
//

#include "wWinMain.h"

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.

    // Initialize global strings
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_AUTOMATICFEVERSCREENING, szWindowClass, MAX_LOADSTRING);
    RegisterMainWindow(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_AUTOMATICFEVERSCREENING));

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}


//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    hInst = hInstance; // Store instance handle in our global variable

    HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    return TRUE;
}


//////////////////////////////////////////////// Main Windows ////////////////////////////////////////////////

//
//  FUNCTION: RegisterMainWindow()
//
//  PURPOSE: Registers the window class.
//
ATOM RegisterMainWindow(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_AUTOMATICFEVERSCREENING));
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    //wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.hbrBackground = NULL;
    wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_AUTOMATICFEVERSCREENING);
    wcex.lpszClassName = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}


//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE: Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    switch (message)
    {
    case WM_COMMAND:
        {
                //Combo boxes
            if (HIWORD(wParam) == CBN_SELCHANGE)
                // If the user makes a selection from the list:
                //   Send CB_GETCURSEL message to get the index of the selected list item.
                //   Send CB_GETLBTEXT message to get the item.
                //   Display the item in a messagebox.
            {
                int ItemIndex = SendMessage((HWND)lParam, (UINT)CB_GETCURSEL,
                    (WPARAM)0, (LPARAM)0);
                TCHAR  ListItem[256];
                (TCHAR)SendMessage((HWND)lParam, (UINT)CB_GETLBTEXT,
                    (WPARAM)ItemIndex, (LPARAM)ListItem);
                gDevice.SetPalleteImage(ItemIndex + 1);
            }

            int wmId = LOWORD(wParam);
            // Parse the menu selections:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_TIM:
                try {
                    if (Imager == NULL) Imager = new PIseries::TIMImager();

                    gDevice.AddNewDevice(&Imager);
                    gDevice.ConfigureDisplay(hWnd, 0, LEFTOUT, TOPOUT, WIDTHOUT, HEIGHTOUT);
                }
                catch (thermoCamera::MyError& e)
                {
                    switch (e)
                    {
                    case thermoCamera::MyError::badInput:
                        MessageBox(hWnd, TEXT("Bad input!"), TEXT("Warning"), MB_OK);
                        break;
                    case thermoCamera::MyError::notInit:
                        MessageBox(hWnd, TEXT("Please, make sure the camera is connected!"), TEXT("Warning"), MB_OK);
                        break;
                    case thermoCamera::MyError::cannotOpenFile:
                        break;
                    case thermoCamera::MyError::dataIsNotValid:
                        break;
                    case thermoCamera::MyError::accessDenied:
                        break;
                    case thermoCamera::MyError::alreadyInit:
                        MessageBox(hWnd, TEXT("Camera is already added!"), TEXT("Information"), MB_OK);
                        break;
                    default:
                        break;
                    }
                }
                break;
            case IDM_CONFIG_RECORD:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_RECORDCONFIG), hWnd, RecordConfig);
                break;
            case IDM_CONFIG_WINDOW:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_WINDOWCONFIG), hWnd, WindowConfig);
                break;
            case IDM_SETTINGS:
                gInterface.DoSettingsConfig(hWnd);
                break;
            case IDM_DISPOSE:
                try {
                    gDevice.RemoveDevice();
                }
                catch (thermoCamera::MyError& e)
                {
                    switch (e)
                    {
                    case thermoCamera::MyError::badInput:
                        MessageBox(hWnd, TEXT("Bad input!"), TEXT("Information"), MB_OK);
                        break;
                    case thermoCamera::MyError::notInit:
                        MessageBox(hWnd, TEXT("Not init!"), TEXT("Information"), MB_OK);
                        break;
                    case thermoCamera::MyError::badSizeOfVideo:
                        MessageBox(hWnd, TEXT("Bad size (width, height) of input device!"), TEXT("Warning"), MB_OK);
                        break;
                    case thermoCamera::MyError::alreadyInit:
                        MessageBox(hWnd, TEXT("Device is already added!"), TEXT("Information"), MB_OK);
                        break;
                    case thermoCamera::MyError::videoNotInit:
                        MessageBox(hWnd, TEXT("Device is not init!"), TEXT("Information"), MB_OK);
                        break;
                    case thermoCamera::MyError::videoIsDeleted:
                        MessageBox(hWnd, TEXT("Device is removed!"), TEXT("Information"), MB_OK);
                        break;
                    case thermoCamera::MyError::deviceIsEmpty:
                        MessageBox(hWnd, TEXT("Device is already empty!"), TEXT("Information"), MB_OK);
                        break;
                    default:
                        break;
                    }
                }

                if (Imager)
                {
                    delete Imager;
                    Imager = NULL;
                }
                gInterface.Delete();

                break;
            case FACE_DETECTION:
                if (gDevice.isFaceDetectionOn())
                {
                    gDevice.StopFaceDetection();
                }
                else
                {
                    gDevice.StartFaceDetection();
                }
                break;
            case ALARMSET:
                gInterface.SetAlarm(hWnd, &gDevice);
                break;
            case CALIBRATE:
                gInterface.SetCalibrateValue(hWnd, &gDevice);
                break;
            case IDM_RECTANGLE_DRAW:
                if (gDevice.isDrawingRectOn())
                {
                    gDevice.ResetDrawingRectangle();
                    CheckMenuItem(GetMenu(hWnd), IDM_RECTANGLE_DRAW, MF_UNCHECKED);
                }
                else
                {
                    gDevice.SetDrawingRectangle();
                    CheckMenuItem(GetMenu(hWnd), IDM_RECTANGLE_DRAW, MF_CHECKED);
                }
                break;
            case IDM_CLEAR_DRAW:
                gDevice.ClearRectangle();
                break;
            case IDM_EXIT:
                SendMessage(hWnd, WM_CLOSE, NULL, NULL);
                break;
            case START_STREAMING:
                try
                {
                    if (gDevice.GetPlaybackStatus())
                    {
                        gDevice.AddRecord(hWnd, 0, LEFTOUT, TOPOUT, WIDTHOUT, HEIGHTOUT);
                        gDevice.Play();
                    }
                    else
                    {
                        gDevice.Play();
                    }
                }
                catch (thermoCamera::MyError& e)
                {
                    switch (e)
                    {
                    case thermoCamera::MyError::badInput:
                        break;
                    case thermoCamera::MyError::notInit:
                        break;
                    case thermoCamera::MyError::cannotOpenFile:
                        MessageBox(hWnd, TEXT("Cannot play the video!"), TEXT("Warning"), MB_OK);
                        break;
                    case thermoCamera::MyError::dataIsNotValid:
                        MessageBox(hWnd, TEXT("Data is not valid!"), TEXT("Warning"), MB_OK);
                        break;
                    case thermoCamera::MyError::accessDenied:
                        MessageBox(hWnd, TEXT("Device is not connected or Record is not set up!"), TEXT("Warning"), MB_OK);
                        break;
                    case thermoCamera::MyError::deviceIsNotConfig:
                        MessageBox(hWnd, TEXT("Configure video display first!"), TEXT("Warning"), MB_OK);
                        break;
                    default:
                        break;
                    }
                }
                break;
            case STOP_STREAMING:
                try
                {
                    gDevice.Stop();
                }
                catch (thermoCamera::MyError& e)
                {
                    switch (e)
                    {
                    case thermoCamera::MyError::cannotOpenFile:
                        MessageBox(hWnd, TEXT("Cannot stop the video!"), TEXT("Warning"), MB_OK);
                        break;
                    default:
                        break;
                    }
                }
                if (gDevice.isFaceDetectionOn())
                {
                    gDevice.StopFaceDetection();
                }
                InvalidateRect(hWnd, NULL, true);
                break;
            case PAUSE_STREAMING:
                try
                {
                    gDevice.Pause();
                }
                catch (thermoCamera::MyError& e)
                {
                    switch (e)
                    {
                    default:
                        break;
                    }
                }
                break;
            case IDM_REDMOUSECOLOR:
                gInterface.SetColorForMouseTemp(RGBRED);
                break;
            case IDM_GREENMOUSECOLOR:
                gInterface.SetColorForMouseTemp(RGBGREEN);
                break;
            case IDM_BLUEMOUSECOLOR:
                gInterface.SetColorForMouseTemp(RGBBLUE);
                break;
            case IDM_BLACKMOUSECOLOR:
                gInterface.SetColorForMouseTemp(RGBBLACK);
                break;
            case IDM_WHITEMOUSECOLOR:
                gInterface.SetColorForMouseTemp(RGBWHITE);
                break;
            case IDM_REDRECTANGLECOLOR:
                gDevice.SetColorRectangle(RGBRED);
                break;
            case IDM_GREENRECTANGLECOLOR:
                gDevice.SetColorRectangle(RGBGREEN);
                break;
            case IDM_BLUERECTANGLECOLOR:
                gDevice.SetColorRectangle(RGBBLUE);
                break;
            case IDM_BLACKRECTANGLECOLOR:
                gDevice.SetColorRectangle(RGBBLACK);
                break;
            case IDM_WHITERECTANGLECOLOR:
                gDevice.SetColorRectangle(RGBWHITE);
                break;
            case IDM_FIRST:
                gInterface.ShowTracker(TRACKER_FIRST,true);
                break;
            case IDM_SECOND:
                gInterface.ShowTracker(TRACKER_SECOND, true);
                break;
            case IDM_THIRD:
                gInterface.ShowTracker(TRACKER_THIRD, true);
                break;
            case IDM_FOURTH:
                gInterface.ShowTracker(TRACKER_FOURTH, true);
                break;
            case IDM_FIFTH:
                gInterface.ShowTracker(TRACKER_FIFTH, true);
                break;
            case IDM_SIXTH:
                gInterface.ShowTracker(TRACKER_SIXTH, true);
                break;
            case IDM_SEVENTH:
                gInterface.ShowTracker(TRACKER_SEVENTH, true);
                break;
            case IDM_EIGTH:
                gInterface.ShowTracker(TRACKER_EIGHTH, true);
                break;
            case IDM_SHOWALL_FACES:
                gInterface.ShowAllTrackers(true);
                break;
            case IDM_HIDEALL_FACES:
                gInterface.HideAllTrackers();
                break;
            case ClICK_ON_TRACKER_FIRST:
                gInterface.ShowTemperatureToEdit(TRACKER_FIRST);
                break;
            case ClICK_ON_TRACKER_SECOND:
                gInterface.ShowTemperatureToEdit(TRACKER_SECOND);
                break;
            case ClICK_ON_TRACKER_THIRD:
                gInterface.ShowTemperatureToEdit(TRACKER_THIRD);
                break;
            case ClICK_ON_TRACKER_FOURTH:
                gInterface.ShowTemperatureToEdit(TRACKER_FOURTH);
                break;
            case ClICK_ON_TRACKER_FIFTH:
                gInterface.ShowTemperatureToEdit(TRACKER_FIFTH);
                break;
            case ClICK_ON_TRACKER_SIXTH:
                gInterface.ShowTemperatureToEdit(TRACKER_SIXTH);
                break;
            case ClICK_ON_TRACKER_SEVENTH:
                gInterface.ShowTemperatureToEdit(TRACKER_SEVENTH);
                break;
            case ClICK_ON_TRACKER_EIGHTH:
                gInterface.ShowTemperatureToEdit(TRACKER_EIGHTH);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_LBUTTONDOWN:
        {
            if (gDevice.isDrawingRectOn())
            {
                POINT left = { 0,0 };
                left.x = LOWORD(lParam);
                left.y = HIWORD(lParam);
                gDevice.SetLeftPointForRectangleDrawing(left);
                gDevice.EnablePaintingRectangle();
            }           
        }
        break;
        case WM_RBUTTONDOWN:
        {
            if (gDevice.isDrawingRectOn())
            {
                gDevice.ClearRectangle();
            }
        }
        break;
        case WM_LBUTTONUP:
        {
            if (gDevice.isDrawingRectOn())
            {
                gDevice.DisablePaintingRectangle();
            }
        }
        break;
        case WM_MOUSEMOVE:
        {
            if (gDevice.isDrawingRectOn())
            {
                if (gDevice.isPaintingRectangleWithMouse())
                {
                    gDevice.UpdateDrawingRectangle();
                }
            }
        }
        break;
    case WM_ERASEBKGND:
    {
        RECT rc;
        GetClientRect(hWnd, &rc);

        TRIVERTEX vertex[2];
        vertex[0].x = rc.left;
        vertex[0].y = rc.top;
        vertex[0].Red = 0xF200;
        vertex[0].Green = 0xF500;
        vertex[0].Blue = 0xF900;
        vertex[0].Alpha = 0x0000;

        vertex[1].x = rc.right;
        vertex[1].y = rc.bottom;
        vertex[1].Red = 0xAC00;
        vertex[1].Green = 0xCD00;
        vertex[1].Blue = 0xF800;
        vertex[1].Alpha = 0x0000;

        GRADIENT_RECT gRect;
        gRect.UpperLeft = 0;
        gRect.LowerRight = 1;
        GradientFill((HDC)wParam, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
 
        return 1L;
    }
            break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            hdc = BeginPaint(hWnd, &ps);

            gInterface.DrawRectangle(hWnd, hdc, 0);

            if (gDevice.isStreaming())
            {
                gInterface.HideNoVideo();
                
                // video
                gDevice.DrawOutput(hdc, gDevice.GetRectangleVideo(INDEX_HBITMAP_OF_VIDEO), gDevice.GetHDCBackBuffer(INDEX_HBITMAP_OF_VIDEO));
                // bar
                gDevice.DrawOutput(hdc, gDevice.GetRectangleVideo(INDEX_HBITMAP_OF_BAR), gDevice.GetHDCBackBuffer(INDEX_HBITMAP_OF_BAR));

                // temp from mouse
                gDevice.DrawTemperature(hdc, gInterface.GetColorForMouseTemp());

                // min max temp for bar
                gDevice.DrawMinMaxBar(hdc, gDevice.GetRectangleVideo(INDEX_HBITMAP_OF_BAR));
                
                if (gDevice.isFaceDetectionOn())
                {
                    gDevice.DrawRectOfFaces(hWnd, hdc);

                    gDevice.DrawTemperatureOfFaces(hWnd, hdc);

                    gInterface.SetNumberOfFaces(hWnd, &gDevice);
                }

                gInterface.DrawTrackers(hWnd, &gDevice);

                gDevice.DrawRectangleOnScreen(hWnd,hdc);
                gDevice.SetTemperatureOfRegion();
                gInterface.SetTemperatureOfRegion(hWnd, &gDevice);
                if (gDevice.isDrawingRectOn())
                {
                    if (gDevice.isPaintingRectangleWithMouse())
                    {
                        gDevice.DrawRectangleOnScreen(hWnd,hdc);
                    }
                }
            }
            else
            {
                gInterface.ShowNoVideo();
            }

            gInterface.ValidateTrackers(gDevice.GetNumOfTrackers(), gDevice.GetAlarmValue());

            gInterface.AddImages(hWnd, hdc);

            EndPaint(hWnd, &ps);
            return 0L;
        }
        break;
    case WM_CREATE:
        {
            GetCurrentDirectory(MAX_PATH, gPathToDirectory);
            gInterface.SetAbsolutePath(gPathToDirectory);
            gInterface.InitLogger();
            gInterface.CreateInterface(hWnd,&gDevice);
            gInterface.InitTrackersForDisplay(hWnd);
            gInterface.AddCombos(hWnd);
            gInterface.AddButtons(hWnd);

            TCHAR txt[MAX_PATH];
            #if UNICODE
                wcscpy_s(txt, MAX_PATH, gPathToDirectory);
                wcscat_s(txt, MAX_PATH, PATH_TO_CASCADE);
            #else
                strcpy_s(txt, MAX_PATH, gPathToDirectory);
                strcat_s(txt, MAX_PATH, PATH_TO_CASCADE);
            #endif
            gDevice.SetPathToClassifier(txt);
        }
        break;
    case WM_SIZE:
        if (gDevice.isAutoSizeSet())
        {
            gDevice.SetAutoSize(LEFTOUT, TOPOUT);
        }
        break;
    case WM_CLOSE:
        {
            try
            {
                gDevice.RemoveDevice();
            }
            catch(thermoCamera::MyError& e)
            {

            }
            gInterface.DrawTrackers(hWnd, &gDevice);
            gInterface.CloseLogger();
            DestroyWindow(hWnd);
        break;
        }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        //return DefWindowProc(hWnd, message, wParam, lParam);
        if (IsWindowUnicode(hWnd))
            return DefWindowProcW(hWnd, message, wParam, lParam);
        else
            return DefWindowProcA(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

// Message handler for record config box.
INT_PTR CALLBACK RecordConfig(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    LPNMHDR     lpnmhdr;

    switch (message)
    {
    case WM_INITDIALOG:
        {
            gInterface.InitRecordConfig(hDlg,&gDevice);
        }
        return (INT_PTR)TRUE;
        // on any command notification, tell the property sheet to enable the Apply button
    case WM_COMMAND:
        PropSheet_Changed(GetParent(hDlg), hDlg);

        if (LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        else if(LOWORD(wParam) == IDOK)
        {
            int ItemIndexWriteRead = 0;
            {
                // Timer Record Congig
                HWND hwndTimeEdit = GetDlgItem(hDlg, IDC_RECORD_TIME_EDIT);
                TCHAR txt[100];
                GetWindowText(hwndTimeEdit, txt, 100);
                unsigned int i = _ttoi(txt);
                gDevice.SetTimerIntervalForRecord(i);
            }

            {
                // Combo Record Config
                HWND hwnd = GetDlgItem(hDlg, IDC_COMB_REC_WR);
                ItemIndexWriteRead = SendMessage((HWND)hwnd, (UINT)CB_GETCURSEL,
                    (WPARAM)0, (LPARAM)0);
                gDevice.SetMethodForRecord(ItemIndexWriteRead);
            }

            {
                // Enable Record Config
                UINT result = IsDlgButtonChecked(hDlg, IDC_ENABLE_RECORD);
                if (result == BST_CHECKED)
                {
                    try
                    {
                        gDevice.Stop();
                    }
                    catch (thermoCamera::MyError& e) {}

                    if(gDevice.GetMethodForRecord() == 0) 
                        gDevice.ChangePlayback(1);
                    else 
                        gDevice.ChangePlayback(0);
                    gDevice.SetRecordFromCamera();
                }
                else if (result == BST_UNCHECKED)
                {
                    try
                    {
                        gDevice.ChangePlayback(0);
                        gDevice.ResetRecordFromCamera();
                        gDevice.RemoveDevice();
                    }
                    catch (thermoCamera::MyError& e)
                    {
                    }
                }   
            }

            //Path to record
            {
                HWND hwndPathEdit = GetDlgItem(hDlg, IDC_RECORD_PATH_EDIT);
                TCHAR txt[MAX_PATH];
                GetWindowText(hwndPathEdit, txt, MAX_PATH);
                if (ItemIndexWriteRead == 1)
                {
                    #if UNICODE 
                        wcscat_s(txt, MAX_PATH, TEXT("\\"));
                    #else
                        strcat_s(txt, MAX_PATH, "\\");
                    #endif
                }
                gDevice.SetPathToRecord(txt);
            }

            {
                // Record only face detected
                UINT result = IsDlgButtonChecked(hDlg, IDC_RECORD_ONLYFACES);
                if (result == BST_CHECKED)
                {
                    gDevice.SetRecordOnlyFaceDetected();
                }
                else if (result == BST_UNCHECKED)
                {
                    gDevice.ResetRecordOnlyFaceDetected();
                }
            }

            
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }

        if (LOWORD(wParam) == IDC_RECORD_FILE_BUTTON)
        {
            // Combo Record Config
            HWND hwnd = GetDlgItem(hDlg, IDC_COMB_REC_WR);
            int ItemIndex = SendMessage((HWND)hwnd, (UINT)CB_GETCURSEL,
                (WPARAM)0, (LPARAM)0);
            if (ItemIndex == 1)
                gInterface.OpenAndSetRecordPathOutput(hDlg, &gDevice);
            else
                gInterface.OpenAndSetRecordPathInput(hDlg, &gDevice);
        }

        break;
    default:
        break;
    }
    return (INT_PTR)FALSE;
}

INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
{
    if (uMsg == BFFM_INITIALIZED) SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
    return 0;
}

INT_PTR CALLBACK WindowConfig(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        gInterface.InitWindowConfig(hDlg, &gDevice);
        return (INT_PTR)TRUE;
        break;

    case WM_COMMAND:

        PropSheet_Changed(GetParent(hDlg), hDlg);

        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            int w = 0;
            int h = 0;
            {
                // Width Window Config
                HWND hwndWidthEdit = GetDlgItem(hDlg, IDC_WINDOW_WIDTH_EDIT);
                TCHAR txt[MAX_PATH];
                GetWindowText(hwndWidthEdit, txt, MAX_PATH);
                w = _ttoi(txt);
                if(w > 100)
                    gDevice.SetWidthVideo(w);
            }

            {
                // Height Window Config
                HWND hwndHeightEdit = GetDlgItem(hDlg, IDC_WINDOW_HEIGHT_EDIT);
                TCHAR txt[MAX_PATH];
                GetWindowText(hwndHeightEdit, txt, MAX_PATH);
                h = _ttoi(txt);
                if (h > 50)
                    gDevice.SetHeightVideo(h);
            }

            // Enable AutoSize Window
            UINT result = IsDlgButtonChecked(hDlg, IDC_ENABLE_AUTOSIZE);
            if (result == BST_CHECKED)
            {
                gDevice.SetAutoSize();
                gDevice.EraseAndUpdateWindow();
                gDevice.SetAutoSize(LEFTOUT, TOPOUT);
            }
            else if (result == BST_UNCHECKED)
            {
                gDevice.ResetAutoSize();
                if (w > 100 && h > 50)
                {                   
                    gDevice.EraseAndUpdateWindow();
                    gDevice.ConfigureBuffer(0, w, h);
                    RECT rec = gDevice.GetRectangleVideo(1);
                    gDevice.ConfigureBuffer(1, rec.right, rec.bottom);
                }
            }

            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

/**************************************************************************

   VideoSettingDlgProc()

**************************************************************************/

LRESULT CALLBACK VideoSettingDlgProc(HWND hDlg,
    UINT uMessage,
    WPARAM wParam,
    LPARAM lParam)
{
    LPNMHDR     lpnmhdr;

    switch (uMessage)
    {
    case WM_INITDIALOG:
        gInterface.InitVideoConfig(hDlg, &gDevice);
        return (INT_PTR)TRUE;
        break;
        // on any command notification, tell the property sheet to enable the Apply button
    case WM_COMMAND:
        PropSheet_Changed(GetParent(hDlg), hDlg);
        break;

    case WM_NOTIFY:
        lpnmhdr = (NMHDR FAR*)lParam;

        switch (lpnmhdr->code)
        {
        case PSN_APPLY:   //sent when OK or Apply button pressed
            {
                // Enable Manual Range
                UINT result = IsDlgButtonChecked(hDlg, IDC_ENABLE_MANUAL_RANGE_TEMPERATURE);
                if (result == true)
                {
                    gDevice.SetManualRangeTemperature();
                }
                else
                {
                    gDevice.ResetManualRangeTemperature();
                }
                
                float value = 0.f;
                {
                    // Min temperature
                    HWND hwnd = GetDlgItem(hDlg, IDC_MIN_VIDEO_TEMP_EDIT);
                    TCHAR txt[MAX_PATH];
                    GetWindowText(hwnd, txt, MAX_PATH);
                    value = _ttof(txt);
                    gDevice.SetMinRangeTemperature(value);
                }

                {
                    // Max temperature
                    HWND hwnd = GetDlgItem(hDlg, IDC_MAX_VIDEO_TEMP_EDIT);
                    TCHAR txt[MAX_PATH];
                    GetWindowText(hwnd, txt, MAX_PATH);
                    value = _ttof(txt);
                    gDevice.SetMaxRangeTemperature(value);
                }

            }
            break;

        case PSN_RESET:   //sent when Cancel button pressed
            break;

        case PSN_SETACTIVE:
            //this will be ignored if the property sheet is not a wizard
            PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
            break;

        default:
            break;
        }
        break;

    default:
        break;
    }

    return FALSE;
}

/**************************************************************************

   FaceSettingDlgProc()

**************************************************************************/

LRESULT CALLBACK FaceSettingDlgProc(HWND hDlg,
    UINT uMessage,
    WPARAM wParam,
    LPARAM lParam)
{
    LPNMHDR     lpnmhdr;

    switch (uMessage)
    {
    case WM_INITDIALOG:
        gInterface.InitFaceSetting(hDlg, &gDevice);
        return (INT_PTR)TRUE;
        break;
        // on any command notification, tell the property sheet to enable the Apply button
    case WM_COMMAND:
        PropSheet_Changed(GetParent(hDlg), hDlg);

        if (LOWORD(wParam) == IDC_CLASSIFIER_FILE_BUTTON)
        {
            // Classifier Path Added
            gInterface.OpenAndSetClassifierPath(hDlg, &gDevice);
        }

        break;

    case WM_NOTIFY:
        lpnmhdr = (NMHDR FAR*)lParam;

        switch (lpnmhdr->code)
        {
        case PSN_APPLY:   //sent when OK or Apply button pressed

            {
                // Enable Face Detection 
                UINT result = IsDlgButtonChecked(hDlg, IDC_ENABLE_FACE_DETECTION);
                if (result == true)
                {
                    gDevice.StartFaceDetection();
                }
                else
                {
                    gDevice.StopFaceDetection();
                }
            }

            {
                // Path to record
                HWND hwndPathEdit = GetDlgItem(hDlg, IDC_CLASSIFIER_PATH_EDIT);
                TCHAR txt[MAX_PATH];
                GetWindowText(hwndPathEdit, txt, MAX_PATH);
                gDevice.SetPathToClassifier(txt);
            }

            break;

        case PSN_RESET:   //sent when Cancel button pressed
            break;

        case PSN_SETACTIVE:
            //this will be ignored if the property sheet is not a wizard
            PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
            return FALSE;

        default:
            break;
        }
        break;

    default:
        break;
    }

    return FALSE;
}

/**************************************************************************

   AlarmSettingDlgProc()

**************************************************************************/

LRESULT CALLBACK AlarmSettingDlgProc(HWND hDlg,
    UINT uMessage,
    WPARAM wParam,
    LPARAM lParam)
{
    LPNMHDR     lpnmhdr;

    switch (uMessage)
    {
    case WM_INITDIALOG:
        gInterface.InitAlarmSetting(hDlg, &gDevice);
        return (INT_PTR)TRUE;
        break;
        // on any command notification, tell the property sheet to enable the Apply button
    case WM_COMMAND:
        PropSheet_Changed(GetParent(hDlg), hDlg);

        if (LOWORD(wParam) == IDC_ALARM_IMAGE_FILE_BUTTON)
        {
            // Alarm path for save image
            gInterface.OpenAndSetAlarmPath(hDlg, &gDevice);
        }

        break;

    case WM_NOTIFY:
        lpnmhdr = (NMHDR FAR*)lParam;

        switch (lpnmhdr->code)
        {
        case PSN_APPLY:   //sent when OK or Apply button pressed

        {
            // Enable Face Detection 
            UINT result = IsDlgButtonChecked(hDlg, IDC_ENABLE_ALARM_SAVING);
            if (result == true)
            {
                gDevice.SetAlarmImageSaving();
            }
            else
            {
                gDevice.ResetAlarmImageSaving();
            }
        }

        {
            // Path to record
            HWND hwndPathEdit = GetDlgItem(hDlg, IDC_ALARM_IMAGE_PATH_EDIT);
            TCHAR txt[MAX_PATH];
            GetWindowText(hwndPathEdit, txt, MAX_PATH);
            gDevice.SetPathToAlarmSaving(txt);
        }

        break;

        case PSN_RESET:   //sent when Cancel button pressed
            break;

        case PSN_SETACTIVE:
            //this will be ignored if the property sheet is not a wizard
            PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
            return FALSE;

        default:
            break;
        }
        break;

    default:
        break;
    }

    return FALSE;
}

/**************************************************************************

   TempSettingDlgProc()

**************************************************************************/

LRESULT CALLBACK TempSettingDlgProc(HWND hDlg,
    UINT uMessage,
    WPARAM wParam,
    LPARAM lParam)
{
    LPNMHDR     lpnmhdr;

    switch (uMessage)
    {
    case WM_INITDIALOG:
        {
            gInterface.InitTempConfig(hDlg, &gDevice);
        }
        return (INT_PTR)TRUE;
        break;
        // on any command notification, tell the property sheet to enable the Apply button
    case WM_COMMAND:
        PropSheet_Changed(GetParent(hDlg), hDlg);

        if (LOWORD(wParam) == IDC_ALARM_IMAGE_FILE_BUTTON)
        {
            // Alarm path for save image
            gInterface.OpenAndSetAlarmPath(hDlg, &gDevice);
        }

        break;

    case WM_NOTIFY:
        lpnmhdr = (NMHDR FAR*)lParam;

        switch (lpnmhdr->code)
        {
        case PSN_APPLY:   //sent when OK or Apply button pressed

            {
                // Combo Temperature Config
                HWND hwnd = GetDlgItem(hDlg, IDC_COMB_TEMP_ABSRELAT);
                int ItemIndex = SendMessage((HWND)hwnd, (UINT)CB_GETCURSEL,
                    (WPARAM)0, (LPARAM)0);
                gDevice.SetTemperatureMethod(ItemIndex);
            }
        break;

        case PSN_RESET:   //sent when Cancel button pressed
            break;

        case PSN_SETACTIVE:
            //this will be ignored if the property sheet is not a wizard
            PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
            return FALSE;

        default:
            break;
        }
        break;

    default:
        break;
    }

    return FALSE;
}

/**************************************************************************

   PropSheetCallback()

**************************************************************************/

void CALLBACK PropSheetCallback(HWND hwndPropSheet, UINT uMsg, LPARAM lParam)
{
    switch (uMsg)
    {
        //called before the dialog is created, hwndPropSheet = NULL, lParam points to dialog resource
    case PSCB_PRECREATE:
    {
        LPDLGTEMPLATE  lpTemplate = (LPDLGTEMPLATE)lParam;

        if (!(lpTemplate->style & WS_SYSMENU))
        {
            lpTemplate->style |= WS_SYSMENU;
        }
    }
    break;

    //called after the dialog is created
    case PSCB_INITIALIZED:
        break;

    }
}
