/*
 * OleView (details.c)
 *
 * Copyright 2006 Piotr Caban
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "main.h"

DETAILS details;
static const WCHAR wszAppID[] = { 'A','p','p','I','D','\0' };
static const WCHAR wszCLSID[] = { 'C','L','S','I','D','\0' };
static const WCHAR wszProgID[] = { 'P','r','o','g','I','D','\0' };
static const WCHAR wszProxyStubClsid32[] = 
    { 'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2','\0' };
static const WCHAR wszTypeLib[] = { 'T','y','p','e','L','i','b','\0' };

static void CreateRegRec(HKEY hKey, HTREEITEM parent, WCHAR *wszKeyName, BOOL addings)
{
    int i=0, j, retEnum;
    HKEY hCurKey;
    DWORD lenName, lenData, valType;
    WCHAR wszName[MAX_LOAD_STRING];
    WCHAR wszData[MAX_LOAD_STRING];
    WCHAR wszTree[MAX_LOAD_STRING];
    const WCHAR wszBinary[] = { '%','0','2','X',' ','\0' };
    const WCHAR wszDots[] = { '.','.','.','\0' };
    const WCHAR wszFormat1[] = { '%','s',' ','[','%','s',']',' ','=',' ','%','s','\0' };
    const WCHAR wszFormat2[] = { '%','s',' ','=',' ','%','s','\0' };
    TVINSERTSTRUCTW tvis;
    HTREEITEM addPlace = parent;

    U(tvis).item.mask = TVIF_TEXT;
    U(tvis).item.cchTextMax = MAX_LOAD_STRING;
    U(tvis).item.pszText = wszTree;
    tvis.hInsertAfter = TVI_LAST;
    tvis.hParent = parent;

    while(TRUE)
    {
        lenName = sizeof(WCHAR[MAX_LOAD_STRING])/sizeof(WCHAR);
        lenData = sizeof(WCHAR[MAX_LOAD_STRING]);

        retEnum = RegEnumValueW(hKey, i, wszName, &lenName,
                NULL, &valType, (LPBYTE)wszData, &lenData);

        if(retEnum != ERROR_SUCCESS)
        {
            if(!i && lstrlenW(wszKeyName) > 1)
            {
                U(tvis).item.pszText = wszKeyName;
                addPlace = TreeView_InsertItemW(details.hReg, &tvis);
                U(tvis).item.pszText = wszTree;
            }
            break;
        }

        if(valType == REG_BINARY)
        {
            WCHAR wszBuf[MAX_LOAD_STRING];

            for(j=0; j<MAX_LOAD_STRING/3-1; j++)
                wsprintfW(&wszBuf[3*j], wszBinary, (int)((unsigned char)wszData[j]));
            wszBuf[(lenData*3>=MAX_LOAD_STRING ? MAX_LOAD_STRING-1 : lenData*3)] = '\0';
            lstrcpyW(wszData, wszBuf);
            lstrcpyW(&wszData[MAX_LOAD_STRING-5], wszDots);
        }

        if(lenName) wsprintfW(wszTree, wszFormat1, wszKeyName, wszName, wszData);
        else wsprintfW(wszTree, wszFormat2, wszKeyName, wszData);

        addPlace = TreeView_InsertItemW(details.hReg, &tvis);

        if(addings && !memcmp(wszName, wszAppID, sizeof(WCHAR[6])))
        {
            lstrcpyW(wszTree, wszName);
            memmove(&wszData[6], wszData, sizeof(WCHAR[MAX_LOAD_STRING-6]));
            lstrcpyW(wszData, wszCLSID);
            wszData[5] = '\\';

            if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey) != ERROR_SUCCESS)
            {
                i++;
                continue;
            }

            tvis.hParent = TVI_ROOT;
            tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);

            lenName = sizeof(WCHAR[MAX_LOAD_STRING]);

            RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);
            RegCloseKey(hCurKey);

            wsprintfW(wszTree, wszFormat2, &wszData[6], wszName);

            SendMessageW(details.hReg, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
            SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);

            tvis.hParent = parent;
        }
        i++;
    }

    i=-1;
    lenName = sizeof(WCHAR[MAX_LOAD_STRING]);

    while(TRUE)
    {
        i++;

        if(RegEnumKeyW(hKey, i, wszName, lenName) != ERROR_SUCCESS) break;

        if(RegOpenKeyW(hKey, wszName, &hCurKey) != ERROR_SUCCESS) continue;

        CreateRegRec(hCurKey, addPlace, wszName, addings);
        SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)addPlace);

        if(addings && !memcmp(wszName, wszProgID, sizeof(WCHAR[7])))
        {
            lenData = sizeof(WCHAR[MAX_LOAD_STRING]);

            RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
            RegCloseKey(hCurKey);

            if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey) != ERROR_SUCCESS)
                continue;
            CreateRegRec(hCurKey, TVI_ROOT, wszData, FALSE);
        }
        else if(addings && !memcmp(wszName, wszProxyStubClsid32, sizeof(WCHAR[17])))
        {
            lenData = sizeof(WCHAR[MAX_LOAD_STRING]);

            RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
            RegCloseKey(hCurKey);

            RegOpenKeyW(HKEY_CLASSES_ROOT, wszCLSID, &hCurKey);

            lenName = sizeof(WCHAR[MAX_LOAD_STRING]);
            RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);

            tvis.hParent = TVI_ROOT;
            wsprintfW(wszTree, wszFormat2, wszCLSID, wszName);
            tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);

            RegCloseKey(hCurKey);

            memmove(&wszData[6], wszData, sizeof(WCHAR[lenData]));
            memcpy(wszData, wszCLSID, sizeof(WCHAR[6]));
            wszData[5] = '\\';

            RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey);

            CreateRegRec(hCurKey, tvis.hParent, &wszData[6], FALSE);

            SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
            tvis.hParent = parent;
        }
        else if(addings && !memcmp(wszName, wszTypeLib, sizeof(WCHAR[8])))
        {
            lenData = sizeof(WCHAR[MAX_LOAD_STRING]);

            RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
            RegCloseKey(hCurKey);

            RegOpenKeyW(HKEY_CLASSES_ROOT, wszTypeLib, &hCurKey);

            lenName = sizeof(WCHAR[MAX_LOAD_STRING]);
            RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);

            tvis.hParent = TVI_ROOT;
            wsprintfW(wszTree, wszFormat2, wszTypeLib, wszName);
            tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);

            RegCloseKey(hCurKey);

            memmove(&wszData[8], wszData, sizeof(WCHAR[lenData]));
            memcpy(wszData, wszTypeLib, sizeof(WCHAR[8]));
            wszData[7] = '\\';
            RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey);

            CreateRegRec(hCurKey, tvis.hParent, &wszData[8], FALSE);

            SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
            tvis.hParent = parent;
        }
        RegCloseKey(hCurKey);
    }
}

static void CreateReg(WCHAR *buffer)
{
    HKEY hKey;
    DWORD lenBuffer=-1, lastLenBuffer, lenTree;
    WCHAR *path;
    WCHAR wszTree[MAX_LOAD_STRING];
    TVINSERTSTRUCTW tvis;
    HTREEITEM addPlace = TVI_ROOT;

    U(tvis).item.mask = TVIF_TEXT;
    U(tvis).item.cchTextMax = MAX_LOAD_STRING;
    U(tvis).item.pszText = wszTree;
    tvis.hInsertAfter = TVI_LAST;
    tvis.hParent = TVI_ROOT;

    path = buffer;
    while(TRUE)
    {
        while(*path != '\\' && *path != '\0') path += 1;

        if(*path == '\\')
        {
            *path = '\0';

            if(RegOpenKeyW(HKEY_CLASSES_ROOT, buffer, &hKey) != ERROR_SUCCESS)
                return;

            lastLenBuffer = lenBuffer+1;
            lenBuffer = lstrlenW(buffer);
            *path = '\\';
            path += 1;

            lenTree = sizeof(WCHAR[MAX_LOAD_STRING]);

            if(RegQueryValueW(hKey, NULL, wszTree, (LONG *)&lenTree) == ERROR_SUCCESS)
            {
                memmove(&wszTree[lenBuffer-lastLenBuffer+3], wszTree,
                        sizeof(WCHAR[lenTree]));
                memcpy(wszTree, &buffer[lastLenBuffer],
                        sizeof(WCHAR[lenBuffer-lastLenBuffer]));

                if(lenTree == 1) wszTree[lenBuffer-lastLenBuffer] = '\0';
                else
                {
                    wszTree[lenBuffer-lastLenBuffer] = ' ';
                    wszTree[lenBuffer-lastLenBuffer+1] = '=';
                    wszTree[lenBuffer-lastLenBuffer+2] = ' ';
                }

                addPlace = TreeView_InsertItemW(details.hReg, &tvis);
            }

            tvis.hParent = addPlace;
            RegCloseKey(hKey);
        }
        else break;
    }

    if(RegOpenKeyW(HKEY_CLASSES_ROOT, buffer, &hKey) != ERROR_SUCCESS) return;

    CreateRegRec(hKey, addPlace, &buffer[lenBuffer+1], TRUE);

    RegCloseKey(hKey);

    SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)addPlace);
    SendMessageW(details.hReg, TVM_ENSUREVISIBLE, 0, (LPARAM)addPlace);
}

void RefreshDetails(HTREEITEM item)
{
    TVITEMW tvi;
    WCHAR wszBuf[MAX_LOAD_STRING];
    WCHAR wszStaticText[MAX_LOAD_STRING];
    const WCHAR wszFormat[] = { '%','s','\n','%','s','\0' };
    BOOL show;

    memset(&tvi, 0, sizeof(TVITEMW));
    memset(&wszStaticText, 0, sizeof(WCHAR[MAX_LOAD_STRING]));
    tvi.mask = TVIF_TEXT;
    tvi.hItem = item;
    tvi.pszText = wszBuf;
    tvi.cchTextMax = MAX_LOAD_STRING;
    SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);

    if(tvi.lParam)
        wsprintfW(wszStaticText, wszFormat, tvi.pszText, ((ITEM_INFO *)tvi.lParam)->clsid);
    else lstrcpyW(wszStaticText, tvi.pszText);

    SetWindowTextW(details.hStatic, wszStaticText);

    SendMessageW(details.hTab, TCM_SETCURSEL, 0, 0);

    if(tvi.lParam && ((ITEM_INFO *)tvi.lParam)->cFlag & SHOWALL)
    {
        if(SendMessageW(details.hTab, TCM_GETITEMCOUNT, 0, 0) == 1)
        {
            TCITEMW tci;
            memset(&tci, 0, sizeof(TCITEMW));
            tci.mask = TCIF_TEXT;
            tci.pszText = wszBuf;
            tci.cchTextMax = sizeof(wszBuf)/sizeof(wszBuf[0]);

            LoadStringW(globals.hMainInst, IDS_TAB_IMPL,
                    wszBuf, sizeof(wszBuf)/sizeof(wszBuf[0]));
            SendMessageW(details.hTab, TCM_INSERTITEMW, 1, (LPARAM)&tci);

            LoadStringW(globals.hMainInst, IDS_TAB_ACTIV,
                    wszBuf, sizeof(wszBuf)/sizeof(wszBuf[0]));
            SendMessageW(details.hTab, TCM_INSERTITEMW, 2, (LPARAM)&tci);
        }
    }
    else
    {
        SendMessageW(details.hTab, TCM_DELETEITEM, 2, 0);
        SendMessageW(details.hTab, TCM_DELETEITEM, 1, 0);
    }

    show = CreateRegPath(item, wszBuf, MAX_LOAD_STRING);
    ShowWindow(details.hTab, show ? SW_SHOW : SW_HIDE);

    /* FIXME Next line deals with TreeView_EnsureVisible bug */
    SendMessageW(details.hReg, TVM_ENSUREVISIBLE, 0,
            SendMessageW(details.hReg, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)TVI_ROOT));
    SendMessageW(details.hReg, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
    if(show) CreateReg(wszBuf);
}

static void CreateTabCtrl(HWND hWnd)
{
    TCITEMW tci;
    WCHAR buffer[MAX_LOAD_STRING];

    memset(&tci, 0, sizeof(TCITEMW));
    tci.mask = TCIF_TEXT;
    tci.pszText = buffer;
    tci.cchTextMax = sizeof(buffer)/sizeof(buffer[0]);

    details.hTab = CreateWindowW(WC_TABCONTROLW, NULL, WS_CHILD|WS_VISIBLE,
            0, 0, 0, 0, hWnd, (HMENU)TAB_WINDOW, globals.hMainInst, NULL);
    ShowWindow(details.hTab, SW_HIDE);

    LoadStringW(globals.hMainInst, IDS_TAB_REG, buffer, sizeof(buffer)/sizeof(buffer[0]));
    SendMessageW(details.hTab, TCM_INSERTITEMW, 0, (LPARAM)&tci);

    details.hReg = CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW, NULL,
            WS_CHILD|WS_VISIBLE|TVS_HASLINES,
            0, 0, 0, 0, details.hTab, NULL, globals.hMainInst, NULL);
}

static LRESULT CALLBACK DetailsProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    int sel;

    switch(uMsg)
    {
        case WM_CREATE:
            {
                const WCHAR wszStatic[] = { 'S','t','a','t','i','c','\0' };

                details.hStatic = CreateWindowW(wszStatic, NULL, WS_CHILD|WS_VISIBLE,
                        0, 0, 0, 0, hWnd, NULL, globals.hMainInst, NULL);
                CreateTabCtrl(hWnd);
            }
            break;
        case WM_SIZE:
            MoveWindow(details.hStatic, 0, 0, LOWORD(lParam), 40, TRUE);
            MoveWindow(details.hTab, 3, 40, LOWORD(lParam)-6, HIWORD(lParam)-43, TRUE);
            MoveWindow(details.hReg, 10, 34, LOWORD(lParam)-26,
                    HIWORD(lParam)-87, TRUE);
            break;
        case WM_NOTIFY:
            if((int)wParam != TAB_WINDOW) break;
            switch(((LPNMHDR)lParam)->code)
            {
                case TCN_SELCHANGE:
                    ShowWindow(details.hReg, SW_HIDE);
                    sel = SendMessageW(details.hTab, TCM_GETCURSEL, 0, 0);

                    if(sel==0) ShowWindow(details.hReg, SW_SHOW);
                    break;
            }
            break;
        default:
            return DefWindowProcW(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

HWND CreateDetailsWindow(HINSTANCE hInst)
{
    WNDCLASSW wcd;
    const WCHAR wszDetailsClass[] = { 'D','E','T','A','I','L','S','\0' };

    memset(&wcd, 0, sizeof(WNDCLASSW));
    wcd.lpfnWndProc = DetailsProc;
    wcd.lpszClassName = wszDetailsClass;
    wcd.hbrBackground = (HBRUSH)COLOR_WINDOW;

    if(!RegisterClassW(&wcd)) return NULL;

    globals.hDetails = CreateWindowExW(WS_EX_CLIENTEDGE, wszDetailsClass, NULL,
            WS_CHILD|WS_VISIBLE, 0, 0, 0, 0, globals.hPaneWnd, NULL, hInst, NULL);

    return globals.hDetails;
}
