/*
 *    Word splitter Implementation
 *
 * Copyright 2006 Mike McCormack
 *
 * 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
 */

#define COBJMACROS

#include "config.h"

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
#include "indexsrv.h"
#include "wine/unicode.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(infosoft);

typedef struct tag_wordbreaker_impl
{
    const IWordBreakerVtbl *lpVtbl;
    LONG ref;
} wordbreaker_impl;

static HRESULT WINAPI wb_QueryInterface( IWordBreaker *iface,
        REFIID riid, LPVOID *ppvObj)
{
    wordbreaker_impl *This = (wordbreaker_impl *)iface;

    TRACE("(%p)->(%s)\n",This,debugstr_guid(riid));

    *ppvObj = NULL;

    if (IsEqualIID(riid, &IID_IUnknown) ||
        IsEqualIID(riid, &IID_IWordBreaker))
    {
        *ppvObj = This;
        return S_OK;
    }

    TRACE("-- E_NOINTERFACE\n");
    return E_NOINTERFACE;
}

static ULONG WINAPI wb_AddRef( IWordBreaker *iface )
{
    wordbreaker_impl *This = (wordbreaker_impl *)iface;
    return InterlockedIncrement(&This->ref);
}

static ULONG WINAPI wb_Release(IWordBreaker *iface)
{
    wordbreaker_impl *This = (wordbreaker_impl *)iface;
    LONG refcount;

    refcount = InterlockedDecrement(&This->ref);
    if (!refcount)
        HeapFree(GetProcessHeap(), 0, This);

    return refcount;
}

static HRESULT WINAPI wb_Init( IWordBreaker *iface,
        BOOL fQuery, ULONG ulMaxTokenSize, BOOL *pfLicense )
{
    TRACE("%d %u\n", fQuery, ulMaxTokenSize);
    *pfLicense = FALSE;
    return S_OK;
}

static HRESULT call_sink( IWordSink *pWordSink, TEXT_SOURCE *ts, UINT len )
{
    HRESULT r;

    if (!len)
        return S_OK;

    TRACE("%d %s\n", len, debugstr_w(&ts->awcBuffer[ts->iCur]));

    r = IWordSink_PutWord( pWordSink, len, &ts->awcBuffer[ts->iCur], len, ts->iCur );
    ts->iCur += len;

    return r;
}

static HRESULT WINAPI wb_BreakText( IWordBreaker *iface,
         TEXT_SOURCE *ts, IWordSink *pWordSink, IPhraseSink *pPhraseSink)
{
    UINT len, state = 0;
    WCHAR ch;

    TRACE("%p %p %p\n", ts, pWordSink, pPhraseSink);

    if (pPhraseSink)
        FIXME("IPhraseSink won't be called\n");

    do
    {
        len = 0;
        while ((ts->iCur + len) < ts->iEnd)
        {
            ch = ts->awcBuffer[ts->iCur + len];

            switch (state)
            {
            case 0: /* skip spaces and punctuation */

                if (!ch || ispunctW(ch) || isspaceW(ch))
                    ts->iCur ++;
                else
                    state = 1;
                break;

            case 1: /* find the end of the word */

                if (ch && !ispunctW(ch) && !isspaceW(ch))
                    len++;
                else
                {
                    call_sink( pWordSink, ts, len );
                    len = 0;
                    state = 0;
                }
                break;

            }
        }
        call_sink( pWordSink, ts, len );

    } while (S_OK == ts->pfnFillTextBuffer( ts ));

    return S_OK;
}

static HRESULT WINAPI wb_ComposePhrase( IWordBreaker *iface,
         const WCHAR *pwcNoun, ULONG cwcNoun,
         const WCHAR *pwcModifier, ULONG cwcModifier,
         ULONG ulAttachmentType, WCHAR *pwcPhrase, ULONG *pcwcPhrase)
{
    FIXME("%p %u %p %u %u %p %p\n", pwcNoun, cwcNoun,
          pwcModifier, cwcModifier, ulAttachmentType, pwcPhrase, pcwcPhrase);
    return S_OK;
}

static HRESULT WINAPI wb_GetLicenseToUse( IWordBreaker *iface, const WCHAR **ppwcsLicense )
{
    FIXME("%p\n", ppwcsLicense);
    *ppwcsLicense = NULL;
    return S_OK;
}

static const IWordBreakerVtbl wordbreaker_vtbl =
{
    wb_QueryInterface,
    wb_AddRef,
    wb_Release,
    wb_Init,
    wb_BreakText,
    wb_ComposePhrase,
    wb_GetLicenseToUse,
};

HRESULT WINAPI wb_Constructor(IUnknown* pUnkOuter, REFIID riid, LPVOID *ppvObject)
{
    wordbreaker_impl *This;
    IWordBreaker *wb;

    TRACE("%p %s %p\n", pUnkOuter, debugstr_guid(riid), ppvObject);

    This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
    if (!This)
        return E_OUTOFMEMORY;

    This->ref = 1;
    This->lpVtbl = &wordbreaker_vtbl;

    wb = (IWordBreaker*) This;

    return IWordBreaker_QueryInterface(wb, riid, ppvObject);
}
