/*
 * PROJECT:     ReactOS Services
 * LICENSE:     GPL - See COPYING in the top level directory
 * FILE:        base/applications/mscutils/servman/propsheet_depends.c
 * PURPOSE:     Property dialog box message handler
 * COPYRIGHT:   Copyright 2006-2009 Ged Murphy <gedmurphy@reactos.org>
 *
 */

#include "precomp.h"

HTREEITEM
AddItemToTreeView(HWND hTreeView,
                  HTREEITEM hParent,
                  LPWSTR lpDisplayName,
                  LPWSTR lpServiceName,
                  ULONG ServiceType,
                  BOOL bHasChildren)
{
    TV_ITEM tvi;
    TV_INSERTSTRUCT tvins;
    LPWSTR lpName;
    DWORD dwSize;

    ZeroMemory(&tvi, sizeof(tvi));
    ZeroMemory(&tvins, sizeof(tvins));

    tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_CHILDREN;
    tvi.pszText = lpDisplayName;
    tvi.cchTextMax = wcslen(lpDisplayName);
    tvi.cChildren = bHasChildren;

    /* Select the image for this service */
    switch (ServiceType)
    {
        case SERVICE_WIN32_OWN_PROCESS:
        case SERVICE_WIN32_SHARE_PROCESS:
            tvi.iImage = IMAGE_SERVICE;
            tvi.iSelectedImage = IMAGE_SERVICE;
            break;

        case SERVICE_KERNEL_DRIVER:
        case SERVICE_FILE_SYSTEM_DRIVER:
            tvi.iImage = IMAGE_DRIVER;
            tvi.iSelectedImage = IMAGE_DRIVER;
            break;

        default:
            tvi.iImage = IMAGE_UNKNOWN;
            tvi.iSelectedImage = IMAGE_UNKNOWN;
            break;
    }

    if (lpServiceName)
    {
        dwSize = wcslen(lpServiceName) + 1;
        /* Attach the service name */
        lpName = (LPWSTR)HeapAlloc(GetProcessHeap(),
                                   0,
                                   dwSize * sizeof(WCHAR));
        if (lpName)
        {
            StringCchCopyW(lpName, dwSize, lpServiceName);
            tvi.lParam = (LPARAM)lpName;
        }
    }

    tvins.item = tvi;
    tvins.hParent = hParent;

    return TreeView_InsertItem(hTreeView, &tvins);
}

static LPARAM
TreeView_GetItemParam(HWND hTreeView,
                      HTREEITEM hItem)
{
    LPARAM lParam = 0;
    TVITEMW tv = {0};

    tv.mask = TVIF_PARAM | TVIF_HANDLE;
    tv.hItem = hItem;

    if (TreeView_GetItem(hTreeView, &tv))
    {
        lParam = tv.lParam;
    }

    return lParam;
}

static VOID
DestroyItem(HWND hTreeView,
            HTREEITEM hItem)
{
    HTREEITEM hChildItem;
    LPWSTR lpServiceName;

    /* Does this item have any children */
    hChildItem = TreeView_GetChild(hTreeView, hItem);
    if (hChildItem)
    {
        /* It does, recurse to that one */
        DestroyItem(hTreeView, hChildItem);
    }

    /* Get the string and free it */
    lpServiceName = (LPWSTR)TreeView_GetItemParam(hTreeView, hItem);
    if (lpServiceName)
    {
        HeapFree(GetProcessHeap(),
                 0,
                 lpServiceName);
    }
}

static VOID
DestroyTreeView(HWND hTreeView)
{
    HTREEITEM hItem;

    /* Get the first item in the top level */
    hItem = TreeView_GetFirstVisible(hTreeView);
    if (hItem)
    {
        /* Kill it and all children */
        DestroyItem(hTreeView, hItem);

        /* Kill all remaining top level items */
        while (hItem)
        {
            /* Are there any more items at the top level */
            hItem = TreeView_GetNextSibling(hTreeView, hItem);
            if (hItem)
            {
                /*  Kill it and all children */
                DestroyItem(hTreeView, hItem);
            }
        }
    }
}

/*
static BOOL
TreeView_GetItemText(HWND hTreeView,
                     HTREEITEM hItem,
                     LPTSTR lpBuffer,
                     DWORD cbBuffer)
{
    TVITEM tv = {0};

    tv.mask = TVIF_TEXT | TVIF_HANDLE;
    tv.hItem = hItem;
    tv.pszText = lpBuffer;
    tv.cchTextMax = (int)cbBuffer;

    return TreeView_GetItem(hTreeView, &tv);
}
*/

static VOID
InitDependPage(PDEPENDDATA pDependData)
{
    /* Initialize the image list */
    pDependData->hDependsImageList = InitImageList(IDI_NODEPENDS,
                                                   IDI_DRIVER,
                                                   GetSystemMetrics(SM_CXSMICON),
                                                   GetSystemMetrics(SM_CXSMICON),
                                                   IMAGE_ICON);

    /* Set the first tree view */
    TV1_Initialize(pDependData, pDependData->pDlgInfo->pService->lpServiceName);

    /* Set the second tree view */
    TV2_Initialize(pDependData, pDependData->pDlgInfo->pService->lpServiceName);
}

/*
 * Dependancies Property dialog callback.
 * Controls messages to the Dependancies dialog
 */
INT_PTR CALLBACK
DependenciesPageProc(HWND hwndDlg,
                     UINT uMsg,
                     WPARAM wParam,
                     LPARAM lParam)
{
    PDEPENDDATA pDependData;

    /* Get the window context */
    pDependData = (PDEPENDDATA)GetWindowLongPtr(hwndDlg,
                                                GWLP_USERDATA);
    if (pDependData == NULL && uMsg != WM_INITDIALOG)
    {
        return FALSE;
    }

    switch (uMsg)
    {
        case WM_INITDIALOG:
        {
            pDependData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEPENDDATA));
            if (pDependData != NULL)
            {
                SetWindowLongPtr(hwndDlg,
                                 GWLP_USERDATA,
                                 (LONG_PTR)pDependData);

                pDependData->pDlgInfo = (PSERVICEPROPSHEET)(((LPPROPSHEETPAGE)lParam)->lParam);
                pDependData->hDependsWnd = hwndDlg;

                InitDependPage(pDependData);
            }
        }
        break;

        case WM_NOTIFY:
        {
            switch (((LPNMHDR)lParam)->code)
            {
                case TVN_ITEMEXPANDING:
                {
                    LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)lParam;

                    if (lpnmtv->action == TVE_EXPAND)
                    {
                        if (lpnmtv->hdr.idFrom == IDC_DEPEND_TREE1)
                        {
                            /* Has this node been expanded before */
                            if (!TreeView_GetChild(pDependData->hDependsTreeView1, lpnmtv->itemNew.hItem))
                            {
                                /* It's not, add the children */
                                TV1_AddDependantsToTree(pDependData, lpnmtv->itemNew.hItem, (LPWSTR)lpnmtv->itemNew.lParam);
                            }
                        }
                        else if (lpnmtv->hdr.idFrom == IDC_DEPEND_TREE2)
                        {
                            /* Has this node been expanded before */
                            if (!TreeView_GetChild(pDependData->hDependsTreeView2, lpnmtv->itemNew.hItem))
                            {
                                /* It's not, add the children */
                                TV2_AddDependantsToTree(pDependData, lpnmtv->itemNew.hItem, (LPWSTR)lpnmtv->itemNew.lParam);
                            }
                        }
                    }
                    break;
                }
            }
            break;
        }

        case WM_COMMAND:
            switch(LOWORD(wParam))
            {

            }
            break;

        case WM_DESTROY:
            DestroyTreeView(pDependData->hDependsTreeView1);
            DestroyTreeView(pDependData->hDependsTreeView2);

            if (pDependData->hDependsImageList)
                ImageList_Destroy(pDependData->hDependsImageList);

            HeapFree(GetProcessHeap(), 0, pDependData);
    }

    return FALSE;
}
