/*
 * Implementation of the Printer User Interface Dialogs
 *
 * Copyright 2006-2007 Detlef Riekenberg
 *
 * 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 <stdarg.h>

#define COBJMACROS
#define NONAMELESSUNION

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "winver.h"
#include "winnls.h"
#include "shellapi.h"

#include "wine/unicode.h"
#include "wine/debug.h"
#include "printui_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(printui);

HINSTANCE PRINTUI_hInstance = NULL;

/* ################################# */

/* Must be in order with OPT_*      */
static const WCHAR optionsW[OPT_MAX+1]={'a','b','c','f','h','j','l','m','n','t','r','v',0};

/* Must be in order with FLAG_*     */
static const WCHAR flagsW[FLAG_MAX+1]={'q','w','y','z','Z',0};


/* ################################
 * get_next_wstr() [Internal]
 *
 * Get the next WSTR, when available
 *
 */

static LPWSTR get_next_wstr(context_t * cx)
{
    LPWSTR  ptr;

    ptr = cx->pNextCharW;
    if (ptr && ptr[0]) {
        cx->pNextCharW = NULL;
        return ptr;
    }

    /* Get the next Parameter, when available */
    if (cx->next_arg < cx->argc) {
        ptr = cx->argv[cx->next_arg];
        cx->next_arg++;
        cx->pNextCharW = NULL;
        return ptr;
    }
    return NULL;
}


/* ################################
 * get_next_wchar() [Internal]
 *
 * Get the next WCHAR from the Commandline or from the File (@ Filename)
 *
 * ToDo: Support Parameter from a File ( "@Filename" )
 *
 */

static WCHAR get_next_wchar(context_t * cx, BOOL use_next_parameter)
{
    WCHAR   c;

    /* Try the next WCHAR in the actual Parameter */
    if (cx->pNextCharW) {
        c = *cx->pNextCharW;
        if (c) {
            cx->pNextCharW++;
            return c;
        }
        /* We reached the end of the Parameter */
        cx->pNextCharW = NULL;
    }

    /* Get the next Parameter, when available and allowed */
    if ((cx->pNextCharW == NULL) && (cx->next_arg < cx->argc) && (use_next_parameter)) {
        cx->pNextCharW = cx->argv[cx->next_arg];
        cx->next_arg++;
    }

    if (cx->pNextCharW) {
        c = *cx->pNextCharW;
        if (c) {
            cx->pNextCharW++;
        }
        else
        {
            /* We reached the end of the Parameter */
            cx->pNextCharW = NULL;
        }
        return c;
    }
    return '\0';
}

/* ################################ */
static BOOL parse_rundll(context_t * cx)
{
    LPWSTR  ptr;
    DWORD   index;
    WCHAR   txtW[2];
    WCHAR   c;


    c = get_next_wchar(cx, TRUE);
    txtW[1] = '\0';

    while (c)
    {

        while ( (c == ' ') || (c == '\t'))
        {
            c = get_next_wchar(cx, TRUE);
        }
        txtW[0] = c;

        if (c == '@') {
            /* read commands from a File */
            ptr = get_next_wstr(cx);
            FIXME("redir not supported: %s\n", debugstr_w(ptr));
            return FALSE;
        }
        else if (c == '/') {
            c = get_next_wchar(cx, FALSE);
            while ( c )
            {
                txtW[0] = c;
                ptr = strchrW(optionsW, c);
                if (ptr) {
                    index = ptr - optionsW;
                    cx->options[index] = get_next_wstr(cx);
                    TRACE(" opt: %s  %s\n", debugstr_w(txtW), debugstr_w(cx->options[index]));
                    c = 0;
                }
                else
                {
                    ptr = strchrW(flagsW, c);
                    if (ptr) {
                        index = ptr - flagsW;
                        cx->flags[index] = TRUE;
                        TRACE("flag: %s\n", debugstr_w(txtW));
                    }
                    else
                    {
                        cx->command = c;
                        cx->subcommand = '\0';
                        TRACE(" cmd: %s\n", debugstr_w(txtW));
                    }

                    /* help has priority over all commands */
                    if (c == '?') {
                        return TRUE;
                    }

                    c = get_next_wchar(cx, FALSE);

                    /* Some commands use two wchar */
                    if ((cx->command == 'd') || (cx->command == 'g') || (cx->command == 'i') ||
                        (cx->command == 'S') || (cx->command == 'X') ){
                        cx->subcommand = c;
                        txtW[0] = c;
                        TRACE(" sub: %s\n", debugstr_w(txtW));
                        c = get_next_wchar(cx, FALSE);
                    }
                }
            }
            c = get_next_wchar(cx, TRUE);

        }
        else
        {
            /* The commands 'S' and 'X' have additional Parameter */
            if ((cx->command == 'S') || (cx->command == 'X')) {

                /* the actual WCHAR is the start from the extra Parameter */
                cx->pNextCharW--;
                TRACE("%d extra Parameter, starting with %s\n", 1 + (cx->argc - cx->next_arg), debugstr_w(cx->pNextCharW));
                return TRUE;
            }
            FIXME("0x%x: %s is unknown\n", c, debugstr_wn(&c, 1));
            return FALSE;
        }

    }
    return TRUE;
}

/*****************************************************
 *      DllMain
 */
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved);

    switch(fdwReason)
    {
        case DLL_WINE_PREATTACH:
            return FALSE;           /* prefer native version */

        case DLL_PROCESS_ATTACH:
            PRINTUI_hInstance = hinstDLL;
            DisableThreadLibraryCalls( hinstDLL );
            break;
    }
    return TRUE;
}


/*****************************************************
 *  PrintUIEntryW                [printui.@]
 *  Commandline-Interface for using printui.dll with rundll32.exe
 *
 */
void WINAPI PrintUIEntryW(HWND hWnd, HINSTANCE hInst, LPCWSTR pCommand, DWORD nCmdShow)
{
    context_t cx;
    BOOL  res = FALSE;

    TRACE("(%p, %p, %s, 0x%x)\n", hWnd, hInst, debugstr_w(pCommand), nCmdShow);

    memset(&cx, 0, sizeof(context_t));
    cx.hWnd = hWnd;
    cx.nCmdShow = nCmdShow;

    if ((pCommand) && (pCommand[0])) {
        /* result is allocated with GlobalAlloc() */
        cx.argv = CommandLineToArgvW(pCommand, &cx.argc);
        TRACE("got %d args at %p\n", cx.argc, cx.argv);

        res = parse_rundll(&cx);
    }

    if (res && cx.command) {
        switch (cx.command)
        {

            default:
            {
                WCHAR   txtW[3];
                txtW[0] = cx.command;
                txtW[1] = cx.subcommand;
                txtW[2] = '\0';
                FIXME("command not implemented: %s\n", debugstr_w(txtW));
            }
        }
    }

    if ((res == FALSE) || (cx.command == '\0')) {
        FIXME("dialog: Printer / The operation was not successful\n");
    }

    GlobalFree(cx.argv);

}
