#include "XCObject.h"

extern Clientdata areastruct;
extern int number_colors;
extern colorindex *colorlist;

extern BOOL COM_autorefresh;

static int check_handle(long handle, int type, objinstptr *thisinst)
{
	objinstptr topinst;
	int i;

	if (thisinst != NULL)
		*thisinst = NULL;

	if (handle != 0) {
		topinst = areastruct.topinstance;
		for (i=0; i<topinst->thisobject->parts; i++)
			if ((long)topinst->thisobject->plist[i] == handle &&
			    (topinst->thisobject->plist[i]->type & type))
				goto found;
	}

	return -1;

found:
	if (thisinst != NULL)
		*thisinst = topinst;
	return i;
}

STDMETHODIMP XCObject_select(IXCObject *This, VARIANT_BOOL doRefresh)
{
	XCObject *obj = (XCObject*)This;
	objinstptr thisinst;
	short idx, *select;

	if ((idx = check_handle(obj->handle, obj->type, &thisinst)) < 0 ||
	    thisinst != areastruct.topinstance)
		return ECODE(XC_E_HANDLE);
	select = allocselect();
	*select = idx;

	if (doRefresh) {
		refresh(NULL, NULL, NULL);
		setoptionmenu();
	}

	return S_OK;
}

STDMETHODIMP XCObject_get_object_handle(IXCObject *This, long *pVal)
{
	XCObject *obj = (XCObject*)This;

	if (check_handle(obj->handle, obj->type, NULL) < 0)
		return ECODE(XC_E_HANDLE);
	*pVal = obj->handle;

	return S_OK;
}

/*
STDMETHODIMP XCObject_get_index(IXCObject *This, short *pVal)
{
	XCObject *obj = (XCObject*)This;
	int idx = check_handle(obj->handle, obj->type, NULL);

	if (idx < 0)
		return ECODE(XC_E_HANDLE);
	*pVal = idx;
	return S_OK;
}
*/

STDMETHODIMP XCObject_get_color(IXCObject *This, int *pVal)
{
	long handle;
	HRESULT hres;
	
	if ((hres = IXCObject_get_object_handle(This, &handle)) != S_OK)
		return hres;
	*pVal = TOGENERIC(&handle)->color;
	
	return S_OK;
}

STDMETHODIMP XCObject_put_color(IXCObject *This, VARIANT newVal)
{
	HRESULT hres;
	int /*cindex,*/ cval;
	long handle;

	if ((hres = VariantChangeType(&newVal, &newVal, 0, VT_I4)) == S_OK) {
		cval = newVal.lVal;
	} else if (newVal.vt == VT_BSTR) {
		char colbuf[64];

		wcstombs(colbuf, newVal.bstrVal, 63);
		colbuf[63] = 0;
		cval = WinNamedColor(colbuf);
		if (cval == -1)
			return ECODE(XC_E_TYPEMISMATCH);
	} else
		return ECODE(XC_E_TYPEMISMATCH);

	addnewcolorentry(cval);
	/*
	for (cindex=0; cindex<number_colors; cindex++)
		if (colorlist[cindex].color.pixel == cval)
			break;

	unselect_all();
	if ((hres = IXCObject_select(This, 0)) != S_OK)
		return hres;
	if (cindex == -1)
		setcolor(NULL, 1, NULL);
	else
		setcolor(colorlist[cindex].cbutton, 0, NULL);
	*/
	if ((hres = IXCObject_get_object_handle(This, &handle)) != S_OK)
		return hres;
	TOGENERIC(&handle)->color = cval;
	IXCObject_update(This, 1);

	return S_OK;
}

STDMETHODIMP XCObject_update(IXCObject *This, VARIANT_BOOL doRefresh)
{
	XCObject *obj = (XCObject*)This;
	objinstptr thisinst;
	int idx;

	if ((idx = check_handle(obj->handle, obj->type, &thisinst)) < 0)
		return ECODE(XC_E_HANDLE);

	switch (obj->type) {
		case ARC:
			calcarc(TOARC(&obj->handle));
			break;
		default:
			break;
	}

	if (doRefresh) {
		calcbbox(thisinst);
		if (COM_autorefresh && thisinst == areastruct.topinstance) {
			if (areastruct.selects > 0 && areastruct.selectlist[0] == idx)
				setoptionmenu();
			refresh(NULL, NULL, NULL);
		}
	}

	return S_OK;
}

PROPERTY_IMPL(XCLineObject, width, width, float, TOPATH)

static wchar_t *borders[] = { L"solid", L"dashed", L"dotted", L"none" /*, L"unclosed", L"closed"*/ };

STDMETHODIMP XCLineObject_put_border(IXCLineObject *This, BSTR newVal)
{
	HRESULT hres;
	long handle;
	int idx;
	u_short value = 0, mask = 0;

	if ((hres = IXCLineObject_get_object_handle(This, &handle)) != S_OK)
		return ECODE(XC_E_HANDLE);
	if ((idx = get_wide_string_index(newVal, borders, 5)) < 0)
		return ECODE(XC_E_INVALIDBORDER);

	switch (idx) {
		case 0: value = NORMAL; mask = (NOBORDER | DASHED | DOTTED); break;
		case 1: value = DASHED; mask = (NOBORDER | DASHED | DOTTED); break;
		case 2: value = DOTTED; mask = (NOBORDER | DASHED | DOTTED); break;
		case 3: value = NOBORDER; mask = (NOBORDER | DASHED | DOTTED); break;
		/*
		case 4: value = UNCLOSED; mask = UNCLOSED; break;
		case 5: value = 0; mask = UNCLOSED; break;
		*/
	}

	TOPATH(&handle)->style &= ~mask;
	TOPATH(&handle)->style |= value;
	IXCLineObject_update(This, 1);

	return S_OK;
}

STDMETHODIMP XCLineObject_get_border(IXCLineObject *This, BSTR *pVal)
{
	HRESULT hres;
	long handle;
	u_short value = 0;

	if (*pVal != NULL) {
		SysFreeString(*pVal);
		*pVal = NULL;
	}
	if ((hres = IXCLineObject_get_object_handle(This, &handle)) != S_OK)
		return ECODE(XC_E_HANDLE);
	value = TOPATH(&handle)->style & (NOBORDER | DASHED | DOTTED);
	switch (value) {
		case NORMAL: value = 0; break;
		case DASHED: value = 1; break;
		case DOTTED: value = 2; break;
		case NOBORDER: value = 3; break;
	}
	*pVal = SysAllocString(borders[value]);

	return S_OK;
}

STDMETHODIMP XCLineObject_put_closed(IXCLineObject *This, VARIANT_BOOL newVal)
{
	HRESULT hres;
	long handle;
	u_short value = 0, mask = 0;

	if ((hres = IXCLineObject_get_object_handle(This, &handle)) != S_OK)
		return ECODE(XC_E_HANDLE);

	value = (newVal == VARIANT_TRUE ? 0 : UNCLOSED);
	mask = UNCLOSED;
	
	TOPATH(&handle)->style &= ~mask;
	TOPATH(&handle)->style |= value;
	return IXCLineObject_update(This, 1);
}

STDMETHODIMP XCLineObject_get_closed(IXCLineObject *This, VARIANT_BOOL *pVal)
{
	HRESULT hres;
	long handle;
	u_short value = 0, mask = 0;

	if ((hres = IXCLineObject_get_object_handle(This, &handle)) != S_OK)
		return ECODE(XC_E_HANDLE);

	*pVal = ((TOPATH(&handle)->style & UNCLOSED) ? VARIANT_FALSE : VARIANT_TRUE);

	return S_OK;
}
