////////////////////////////////////////////////////////////////////////////////
// GLLineEdit.h
// Copyright Bjoern Ganster 2007-2010
////////////////////////////////////////////////////////////////////////////////

#include "Font.h"
#include "GLLineEdit.h"

#define FILE_NUMBER FILE_NO_GL_LINE_EDIT_CPP

////////////////////////////////////////////////////////////////////////////////
// Constructor

GLLineEdit::GLLineEdit (GLWindow* _parent, int _left, int _top, 
   int _width, int _height)
: GLWindow ("GLLineEdit", GLLineEdit_ID, _parent, _left, _top, _width, _height),
  textColor (0,0,0),
  cursorPos (0)
{
   backgroundColor = Color (1, 1, 1);
}

////////////////////////////////////////////////////////////////////////////////
// Destructor

GLLineEdit::~GLLineEdit()
{
}

////////////////////////////////////////////////////////////////////////////////
// Render

void GLLineEdit::render(int x, int y, int w, int h)
{
	Font* font = getDefaultFont();
	if (font == nullptr) {
		return;
	}

	SET_SCOPE;
	prepareToRender(x, y, w, h);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_DEPTH_TEST);
	textColor.glColor();
	glTranslated (-1.0, 1.0, 0.0);
	glScaled(2 / ((double) getWidth()), -2/((double) getHeight()), 1.0);
	glDepthMask(0);

	// Render text. todo: store text in a texture (with cursor), then simply render that ...
	SET_OP;
	int textTop = (height - font->getCharHeight()) / 2;
	font->renderText(getText(), 2, textTop, width);

	SET_OP;
	text.convertToCP(CP_ASCII);
	char* cp = text.getPtr<char>();

	// Render cursor
	// todo: render cursor only if this line edit has focus
	SET_OP;
	int screenPos = font->textWidth(cp);
	glColor3d(0, 0, 0);
	glBegin (GL_LINES);
		glVertex2i (2+screenPos, textTop);
		glVertex2i (2+screenPos, textTop + font->getCharHeight());
	glEnd ();

	glDepthMask(~0);
	RETURN;
}

////////////////////////////////////////////////////////////////////////////////
// Events

// todo: allow cursor movement
void GLLineEdit::keypressed (BGKey key, bool shiftHeld, bool /*ctrlHeld*/, bool down, bool repeat)
{
   if (!down) {
      return;
   }

   SET_SCOPE;
   BGCPString str;
   switch (key) {
      case 8: // Backspace
         if (cursorPos > 0)
            str = text.copyPart(0, cursorPos-1);
         else
            str.clear();
         str += text.copyPart (cursorPos, text.getByteCount());
         text = str;
         if (cursorPos > 0)
            cursorPos--;
         break;
      case 127: // Delete key
         str = text.copyPart(0, cursorPos);
         str += text.copyPart(cursorPos+1, text.getByteCount());
         text = str;
         break;
      case SDLK_LEFT:
         if (cursorPos > 0)
            cursorPos--;
         break;
      case SDLK_RIGHT:
         if (cursorPos < (int) text.getByteCount()) 
            cursorPos++;
         break;
      case SDLK_HOME:
         cursorPos = 0;
         break;
      case SDLK_END:
         cursorPos = (int) text.getByteCount();
         break;
      case SDLK_RSHIFT:
      case SDLK_LSHIFT:
         break;
      default:
         if (key >= 32) { // Append normal key
            str = text.copyPart (0, cursorPos);

            if (key >='a' && key <= 'z' && shiftHeld) {
                key -= 32;
            }

            str += (char) key;
            str.appendPart (text.getPtr<char>(), cursorPos, text.getByteCount());
            text = str;
            cursorPos++;
         } else { // Print unknown key
            BGCPString str = "Pressed key ";
            str += BGCPString::fromInt(key);
            str.printLn ();
         }
   }

   sendMessage (listener, ValueChangedEvent);
   RETURN;
}

////////////////////////////////////////////////////////////////////////////////
// Button state changed over a window: returns child that was clicked

GLWindow* GLLineEdit::buttonStateChanged (int button, bool down, int x, int y)
{
	Font* font = getDefaultFont();
	if (font == nullptr) {
		return nullptr;
	}

    if (button == 1 && !down) {
		SET_SCOPE;
		int screenPos;
		cursorPos= text.getByteCount();
		bool doContinue;

		do {
			SET_OP;
			BGCPString str = BGCPString (text.getPtr<char>(), cursorPos, text.getCP());
			screenPos = font->textWidth (str);

			if (left + screenPos + 2 > x && cursorPos > 0) {
				--cursorPos;
				doContinue = true;
			} else
				doContinue = false;
		} while (doContinue);

		RETURN this;
   } else
      return NULL;
}

void GLLineEdit::mouseMoved (int /*x*/, int /*y*/)
{
}

////////////////////////////////////////////////////////////////////////////////
// Event: widget looses focus

void GLLineEdit::loseFocus ()
{
}

////////////////////////////////////////////////////////////////////////////////
// Try to interpret text as numerical values

bool GLLineEdit::getDouble (double& value) const
{
	SET_SCOPE;
    value = text.toDouble();
    RETURN true;
}

