/* Uprising - Windows Shell Extension for Subversion
 * Copyright (C) 2001-2002  Jay Freeman (saurik)
*/

/*
 *        Redistribution and use in source and binary
 * forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer in the documentation
 *    and/or other materials provided with the
 *    distribution.
 * 3. The name of the author may not be used to endorse
 *    or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "stdafx.h"

#include "AutoPool.h"
#include "ColumnProvider.h"
#include "Status.h"

namespace Uprising {

STDMETHODIMP ColumnProvider::Initialize(LPCSHCOLUMNINIT psci) {
	return S_OK;
}

STDMETHODIMP ColumnProvider::GetColumnInfo(DWORD dwIndex, SHCOLUMNINFO *psci) {
	if (dwIndex > 3) return S_FALSE;

	switch (dwIndex) {
		case 0: // Revision
			psci->scid.fmtid	= __uuidof(ColumnProvider);
			psci->scid.pid		= 0;
			psci->vt			= VT_I4;
			psci->fmt			= LVCFMT_RIGHT;
			psci->csFlags		= SHCOLSTATE_TYPE_INT;
			psci->cChars		= 6;

			lstrcpynW(psci->wszTitle,		L"Revision", MAX_COLUMN_NAME_LEN);
			lstrcpynW(psci->wszDescription,	L"Subversion: Local Revision", MAX_COLUMN_DESC_LEN);
		break;

		case 1: // Committed Revision
			psci->scid.fmtid	= __uuidof(ColumnProvider);
			psci->scid.pid		= 1;
			psci->vt			= VT_I4;
			psci->fmt			= LVCFMT_RIGHT;
			psci->csFlags		= SHCOLSTATE_TYPE_INT;
			psci->cChars		= 6;

			lstrcpynW(psci->wszTitle,		L"Committed", MAX_COLUMN_NAME_LEN);
			lstrcpynW(psci->wszDescription,	L"Subversion: Last Committed Revision", MAX_COLUMN_DESC_LEN);
		break;

		case 2: // Last Author
			psci->scid.fmtid	= __uuidof(ColumnProvider);
			psci->scid.pid		= 2;
			psci->vt			= VT_BSTR;
			psci->fmt			= LVCFMT_LEFT;
			psci->csFlags		= SHCOLSTATE_TYPE_STR;
			psci->cChars		= 16;

			lstrcpynW(psci->wszTitle,		L"Last Author", MAX_COLUMN_NAME_LEN);
			lstrcpynW(psci->wszDescription,	L"Subversion: Last Commiting Author", MAX_COLUMN_DESC_LEN);
		break;

		case 3: // Text Status
			psci->scid.fmtid	= __uuidof(ColumnProvider);
			psci->scid.pid		= 3;
			psci->vt			= VT_BSTR;
			psci->fmt			= LVCFMT_LEFT;
			psci->csFlags		= SHCOLSTATE_TYPE_STR;
			psci->cChars		= 12;

			lstrcpynW(psci->wszTitle,		L"Text Status", MAX_COLUMN_NAME_LEN );
			lstrcpynW(psci->wszDescription,	L"Subversion: WC Text Status", MAX_COLUMN_DESC_LEN );
		break;
	}

	return S_OK;
}

STDMETHODIMP ColumnProvider::GetItemData(LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvarData) {
	if (pscid->fmtid != __uuidof(ColumnProvider))
		return S_FALSE;
	if (pscid->pid > 3)
		return S_FALSE;

	AutoPool pool(NULL);
	svn_error_init_pool(pool);

	char evilbuf[MAX_PATH];
	_snprintf(evilbuf, MAX_PATH, "%S", pscd->wszFile);
	svn_stringbuf_t *pathbuf = svn_stringbuf_create(evilbuf, pool);
	svn_path_internal_style(pathbuf);

	svn_wc_status_t *status = NULL;
	svn_wc_status(&status, pathbuf, pool);

	if (status == NULL)
		return S_FALSE;

	svn_wc_entry_t *entry = status->entry;

	::VariantClear(pvarData);

	switch (pscid->pid) {
		case 0: // Revision
			if (entry == NULL)
				return S_FALSE;
			::VariantChangeType(pvarData, pvarData, VARIANT_NOVALUEPROP, VT_I4);
			pvarData->lVal = status->entry->revision;
		break;

		case 1: // Committed Revision
			if (entry == NULL)
				return S_FALSE;
            ::VariantChangeType(pvarData, pvarData, VARIANT_NOVALUEPROP, VT_I4);
            pvarData->lVal = entry->cmt_rev;
        break;

        case 2: { // Last Author
			if (entry == NULL)
				return S_FALSE;
            ::VariantChangeType(pvarData, pvarData, VARIANT_NOVALUEPROP, VT_BSTR);

            int length = ::MultiByteToWideChar(CP_ACP, 0, entry->cmt_author->data, -1, NULL, 0);
            wchar_t *buff = new wchar_t[length];
            ::MultiByteToWideChar(CP_ACP, 0, entry->cmt_author->data, -1, buff, length);

			pvarData->bstrVal = ::SysAllocString(buff);

            delete [] buff;
        } break;

		case 3: // Text Status
			::VariantChangeType(pvarData, pvarData, VARIANT_NOVALUEPROP, VT_BSTR);
			pvarData->bstrVal = ::SysAllocString(Status[status->text_status]);
		break;
	}

	return S_OK;
}

}