/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_shell.hxx"

#include "sysmailclient.hxx"
#include "sysmailmsg.hxx"

#include <com/sun/star/system/MailClientFlags.hpp>
#include <com/sun/star/system/XMailMessage.hpp>

#include <osl/diagnose.h>
#include <osl/process.h>
#include <rtl/bootstrap.hxx>
#include <osl/file.hxx>
#include <rtl/ustrbuf.hxx>

#define WIN32_LEAN_AND_MEAN
#if defined _MSC_VER
#pragma warning(push, 1)
#endif
#include <windows.h>
#include <mapi.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif

#include <process.h>
#include <vector>

using css::uno::UNO_QUERY;
using css::uno::Reference;
using css::uno::Exception;
using css::uno::RuntimeException;
using css::uno::Sequence;
using css::lang::IllegalArgumentException;

using css::system::XMailClient;
using css::system::XMailMessage;
using css::system::XMailMessage;
using css::system::MailClientFlags::NO_USER_INTERFACE;
using css::system::MailClientFlags::NO_LOGON_DIALOG;

using rtl::OUString;
using rtl::OUStringBuffer;

namespace shell
{
namespace /* private */
{
    typedef std::vector<rtl::OUString> StringList_t;
    typedef StringList_t::const_iterator StringListIterator_t;

    const rtl::OUString TO = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--to"));
    const rtl::OUString CC = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--cc"));
    const rtl::OUString BCC = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--bcc"));
    const rtl::OUString FROM = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--from"));
    const rtl::OUString SUBJECT = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--subject"));
    const rtl::OUString BODY = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--body"));
    const rtl::OUString ATTACH = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--attach"));
    const rtl::OUString FLAG_MAPI_DIALOG = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--mapi-dialog"));
    const rtl::OUString FLAG_MAPI_LOGON_UI = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("--mapi-logon-ui"));

    static OUString quoteString( const OUString& rStr )
    {
        rtl::OUStringBuffer quoted;
        quoted.append(sal_Unicode('"'));
        quoted.append(rStr);
        quoted.append(sal_Unicode('"'));

        return quoted.makeStringAndClear();
    }

    static OUString quoteAndEscape( const OUString &rStr )
    {
        OUStringBuffer aBuffer;
        aBuffer.append(sal_Unicode('"'));

        sal_Int32 nIndex = rStr.indexOf(sal_Unicode('"'));
        if ( nIndex == -1 )
            aBuffer.append( rStr );
        else
        {
            const sal_Unicode *pStart = rStr.getStr();
            const sal_Unicode *pFrom = pStart;
            const sal_Int32 nLen = rStr.getLength();
            sal_Int32 nPrev = 0;
            do
            {
                aBuffer.append( pFrom, nIndex - nPrev );
                aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\\\"" ) );
                nIndex++;
                pFrom = pStart + nIndex;
                nPrev = nIndex;
            }
            while ( ( nIndex = rStr.indexOf( '"' , nIndex ) ) != -1  );

            aBuffer.append( pFrom, nLen - nPrev );
        }

        aBuffer.append(sal_Unicode('"'));

        return aBuffer.makeStringAndClear();
    }

    /** @internal
        look if an alternative program is configured
        which should be used as senddoc executable */
    static rtl::OUString getAlternativeSenddocUrl()
    {
        rtl::OUString altSenddocUrl;
        HKEY hkey;
        LONG lret = RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\OpenOffice\\SendAsEMailClient", &hkey);
        if (lret == ERROR_SUCCESS)
        {
            wchar_t buff[MAX_PATH];
            LONG sz = sizeof(buff);
            lret = RegQueryValueW(hkey, NULL, buff, &sz);
            if (lret == ERROR_SUCCESS)
            {
                osl::FileBase::getFileURLFromSystemPath(reinterpret_cast<const sal_Unicode*>(buff), altSenddocUrl);
            }
            RegCloseKey(hkey);
        }
        return altSenddocUrl;
    }

    /**
        Returns the absolute file Url of the senddoc executable.

        @returns
        the absolute file Url of the senddoc executable. In case
        of an error an empty string will be returned.
    */
    static rtl::OUString getSenddocUrl()
    {
        rtl::OUString senddocUrl = getAlternativeSenddocUrl();

        if (senddocUrl.getLength() == 0)
        {
            senddocUrl = rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "$OOO_BASE_DIR/program/senddoc.exe"));
            rtl::Bootstrap::expandMacros(senddocUrl); //TODO: detect failure
        }
        return senddocUrl;
    }

    /**
        Execute Senddoc.exe which a MAPI wrapper.
        @param rCommandArgs
                [in] the arguments to be passed to Senddoc.exe
        @returns
                <TRUE/> on success.
    */
    static bool executeSenddoc(const StringList_t& rCommandArgs)
    {
        rtl::OUString senddocUrl = getSenddocUrl();
        if (senddocUrl.getLength() == 0)
            return false;

        oslProcess proc;
        oslProcessError err = osl_Process_E_Unknown;

        /* for efficiency reasons we are using a 'bad' cast here
        as a vector or rtl::OUStrings is nothing else than
        an array of pointers to rtl_uString's */
        err = osl_executeProcess(
            senddocUrl.pData,
            (rtl_uString**)&rCommandArgs[0],
            rCommandArgs.size(),
            osl_Process_WAIT | osl_Process_DETACHED,
            NULL,
            NULL,
            NULL,
            0,
            &proc);

        if (err != osl_Process_E_None)
            return false;

        oslProcessInfo procInfo;
        procInfo.Size = sizeof(oslProcessInfo);
        osl_getProcessInfo(proc, osl_Process_EXITCODE, &procInfo);
        osl_freeProcessHandle(proc);
        return (procInfo.Code == SUCCESS_SUCCESS);
    }
} // namespace private


Reference<XMailMessage> SAL_CALL WinSysMailClient::createMailMessage()
    throw (RuntimeException)
{
    return Reference<XMailMessage>( new WinSysMailMsg() );
}

/**
    Assemble a command line for SendDoc.exe out of the members
    of the supplied XMailMessage.

    @param xMailMessage
    [in] the mail message.

    @param aFlags
    [in] different flags to be used with the system mail service.

    @param rCommandArgs
    [in|out] a buffer for the command line arguments. The buffer
    is assumed to be empty.

    @throws com::sun::star::lang::IllegalArgumentException
    if an invalid file URL has been detected in the attachment list.
*/
void WinSysMailClient::assembleCommandLine(
    const Reference<XMailMessage>& xMailMessage,
    sal_Int32 aFlag,
    StringList_t& rCommandArgs)
{
    OSL_ENSURE(rCommandArgs.size() == 0, "Provided command argument buffer not empty");

    rtl::OUString to = xMailMessage->getRecipient();
    if (to.getLength() > 0)
    {
        rCommandArgs.push_back(TO);
        rCommandArgs.push_back(to);
    }

    Sequence<rtl::OUString> ccRecipients = xMailMessage->getCcRecipient();
    for (int i = 0; i < ccRecipients.getLength(); i++)
    {
        rCommandArgs.push_back(CC);
        rCommandArgs.push_back(ccRecipients[i]);
    }

    Sequence<rtl::OUString> bccRecipients = xMailMessage->getBccRecipient();
    for (int i = 0; i < bccRecipients.getLength(); i++)
    {
        rCommandArgs.push_back(BCC);
        rCommandArgs.push_back(bccRecipients[i]);
    }

    rtl::OUString from = xMailMessage->getOriginator();
    if (from.getLength() > 0)
    {
        rCommandArgs.push_back(FROM);
        rCommandArgs.push_back(from);
    }

    Sequence<rtl::OUString> attachments = xMailMessage->getAttachement();
    for (int i = 0; i < attachments.getLength(); i++)
    {
        rtl::OUString sysPath;
        osl::FileBase::RC err = osl::FileBase::getSystemPathFromFileURL(attachments[i], sysPath);
        if (err != osl::FileBase::E_None)
            throw IllegalArgumentException(
                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Invalid attachment file URL")),
                static_cast<XMailClient*>(this),
                1);

        rCommandArgs.push_back(ATTACH);
        rCommandArgs.push_back( quoteString( sysPath ) );
    }

    rtl::OUString body = xMailMessage->getBody();
    if (body.getLength()>0)
    {
        rCommandArgs.push_back(BODY);
        rCommandArgs.push_back( quoteAndEscape( body ) );
    }

    rtl::OUString subject = xMailMessage->getSubject();
    if (subject.getLength() > 0)
    {
        rCommandArgs.push_back(SUBJECT);
        rCommandArgs.push_back( quoteAndEscape( subject ) );
    }

    if (!(aFlag & NO_USER_INTERFACE))
        rCommandArgs.push_back(FLAG_MAPI_DIALOG);

    if (!(aFlag & NO_LOGON_DIALOG))
        rCommandArgs.push_back(FLAG_MAPI_LOGON_UI);
}

void SAL_CALL WinSysMailClient::sendMailMessage(
    const Reference<XMailMessage>& xMailMessage,
    sal_Int32 aFlag)
    throw (IllegalArgumentException, Exception, RuntimeException)
{
    validateParameter(xMailMessage, aFlag);

    StringList_t senddocParams;
    assembleCommandLine(xMailMessage, aFlag, senddocParams);

    if (!executeSenddoc(senddocParams))
        throw Exception(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Send email failed")),
            static_cast<XMailClient*>(this));
}

void WinSysMailClient::validateParameter(
    const Reference<XMailMessage>& xMailMessage,
    sal_Int32 aFlag )
{
    if (!xMailMessage.is())
        throw IllegalArgumentException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Empty mail message reference")),
            static_cast<XMailClient*>(this),
            1);

    // #93077#
    OSL_ENSURE(!(aFlag & NO_LOGON_DIALOG), "Flag NO_LOGON_DIALOG has currently no effect");

    // check the flags, the allowed range is 0 - (2^n - 1)
    if (aFlag < 0 || aFlag > 3)
        throw IllegalArgumentException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Invalid flag value")),
            static_cast<XMailClient*>(this),
            2);

    // check if a recipient is specified of the flags NO_USER_INTERFACE is specified
    if ((aFlag & NO_USER_INTERFACE) && !xMailMessage->getRecipient().getLength())
        throw IllegalArgumentException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No recipient specified")),
            static_cast<XMailClient*>(this),
            1);
}

}
