/***************************************************************************
                          menuitem.cpp  -  description
                             -------------------
    begin                : Tue Feb 29 2000
    copyright            : (C) 2000 by Michael Speck
    email                : 
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "menuitem.h"
#include <string.h>
#include <stdlib.h>

extern Sdl sdl;
extern DrawRgn dr_src, dr_dst;

MenuItem::MenuItem() //separator
{
	type = ET_SEPARATOR;
	strcpy(name, " ");
	Enlight(0);
	alpha = 255;
	used = 0;
}

MenuItem::MenuItem(char *n) //separator
{
	type = ET_SEPARATOR;
	strcpy(name, n);
	Enlight(0);
	alpha = 255;
	used = 0;
}

MenuItem::MenuItem(char *n, int *p, char *cap1, char *cap2) //switch group
{
	type = ET_SWITCHGRP;
	strcpy(name, n);
	
	sw_cap = new char*[2];
	sw_cap[0] = cap1;
	sw_cap[1] = cap2;
	sw_cap_num = 2;
	
	Enlight(0);
	pos = p;
	alpha = 255;
	min = 0;
	max = 1;
	step = 1;
	used = 0;
}

MenuItem::MenuItem(char *n, int *p, char **caps, int num) //switch group
{
	type = ET_SWITCHGRP;
	strcpy(name, n);
	
	sw_cap = new char*[num];
	for (int i = 0; i < num; i++)
	    sw_cap[i] = caps[i];
	sw_cap_num = num;
	
	Enlight(0);
	pos = p;
	alpha = 255;
	min = 0;
	max = num-1;
	step = 1;
	used = 0;
}

MenuItem::MenuItem(char *n, int *p, int min, int max, int s) //range
{
	type = ET_RANGE;
	strcpy(name, n);
	Enlight(0);
	pos = p;
	alpha = 255;
	step = s;
	MenuItem::min = min;
	MenuItem::max = max;
	used = 0;
}

MenuItem::MenuItem(char *n, int *p, char *k) //restr_keys
{
	type = ET_KEY;
	strcpy(name, n);
	Enlight(0);
	pos = p;
	alpha = 255;
	used = 0;
}

MenuItem::MenuItem(char *n, int a_id) //action
{
	type = ET_ACTION;
	strcpy(name, n);
	Enlight(0);
	alpha = 255;
	action = a_id;
	used = 0;
}

MenuItem::MenuItem(char *n, Menu* m) //submenu
{
	type = ET_SUBMENU;
	strcpy(name, n);
	submenu = m;
	Enlight(0);
	alpha = 255;
	used = 0;
}

MenuItem::MenuItem(char *n, char *p, int m) //string
{
	type = ET_STRING;
	strcpy(name, n);
	Enlight(0);
	alpha = 255;
	max = m;
	pos = (int*)p;
	min = strlen((char*)p);
	used = 0;
}

MenuItem::~MenuItem()
{
    if (type == ET_SWITCHGRP)
        delete sw_cap;
}

void MenuItem::SetXY(int x, int y)
{
	MenuItem::x = x;
	MenuItem::y = y;
}

void MenuItem::SetBackgnd(SDL_Surface *backgnd)
{
	MenuItem::backgnd = backgnd;
}

void MenuItem::SetSubmenu(Menu* m)
{
}

void MenuItem::SetFont(SFnt *fnt, SFnt *enlgt_fnt)
{
	font = fnt;
	enlgt_font = enlgt_fnt;
}

void MenuItem::ComputeStr()
{
	switch (type) {
		case ET_STRING:
			sprintf(string, "%s: %s", name, (char*)pos);
			break;
		case ET_SWITCHGRP:
			sprintf(string, "%s %s", name, sw_cap[*pos]);
			break;
		case ET_RANGE:
			sprintf(string, "%s %i", name, *pos);
			break;
		case ET_KEY:
			if (*pos > 32 && *pos < 127)
				sprintf(string, "%s: '%c'", name, (char)*pos);
			else
				if (*pos == 0)
					sprintf(string, "%s: ???", name);
				else
					switch (*pos){
						case SDLK_UP:
							sprintf(string, "%s: Up", name);
							break;
						case SDLK_DOWN:
							sprintf(string, "%s: Down", name);
							break;
						case SDLK_LEFT:
							sprintf(string, "%s: Left", name);
							break;
						case SDLK_RIGHT:
							sprintf(string, "%s: Right", name);
							break;
						case SDLK_SPACE:
							sprintf(string, "%s: Space", name);
							break;
						default:
							sprintf(string, "%s: %i", name, *pos);
					}
			break;
		default:
			strcpy(string, name);
			break;
	}
	ComputeSize();
}

void MenuItem::Enlight(int t)
{
	if (t) {
		if (!enlighted)
			changed = 1;
		else
			changed = 0;
		enlighted = 1;
		alpha = 0;
	}
	else {
		if (enlighted)
			changed = 1;
		else
			changed = 0;
		enlighted = 0;
	}
}

int MenuItem::Type()
{
	return type;
}

int MenuItem::KeyEvent(int code)
{
	if (type == ET_SWITCHGRP || type == ET_RANGE) {
		int val = *pos;
		switch (code) {
			case SDLK_LEFT:
				val -= step;
				if (val < min)
			        val = max - ((max - min) % step);
            	used = 1;
				break;
			case SDLK_RIGHT:
				val += step;
				if (val > max) val = min;
            	used = 1;
				break;
		}
		if (val != *pos) {
			*pos = val;
			StrUpdate();
		}
		return MR_CONTINUE;
	}
	else
		if (type == ET_KEY && code == SDLK_RETURN){
			*pos = 0;
			StrUpdate();
		}
	return MR_CONTINUE;
}

void MenuItem::SetKey(int code)
{
	if (*pos == 0) {
		*pos = code;
		StrUpdate();
	}
}

void MenuItem::Update()
{
	if (!changed) return;
	//redraw in buffer
	if (enlighted) {
		if (alpha > 0) {
		    SFnt_Write(font, sdl.scr, x, y, string, 0);
		    SFnt_Write(enlgt_font, sdl.scr, x, y, string, alpha);
		}
		else
		    SFnt_Write(enlgt_font, sdl.scr, x, y, string, 0);
	}
	else {
	    SFnt_Write(font, sdl.scr, x, y, string, 0);
		if (alpha < 255)
		    SFnt_Write(enlgt_font, sdl.scr, x, y, string, alpha);
	}
	changed = 0;
}

void MenuItem::SetChanged(int c)
{
	changed = c;
}

void MenuItem::Hide()
{
	if (dw != -1) {
	    DR_SETDST(sdl.scr, dx, dy, dw, dh);
	    DR_SETSRC(backgnd, dx, dy);
		SSur_Blit();
    }		
}

void MenuItem::Refresh()
{
	SDL_UpdateRect(sdl.scr, dx, dy, dw, dh);
}

void MenuItem::ComputeSize()
{
	dw = SFnt_TextWidth(font, string);
	dh = font->lh;
	dx = x - (dw >> 1);
	dy = y - (dh >> 1);
}

void MenuItem::Compute()
{
	if (alpha < 255  && !enlighted) {
		alpha += 3;
		changed = 1;
	}
	else
		if (alpha >= 5 && enlighted) {
			alpha -= 3;
			changed = 1;
		}
}

Menu* MenuItem::Submenu()
{
	return submenu;
}

int MenuItem::ActionId()
{
	return action;
}

void MenuItem::ClearAlpha()
{
	alpha = 255;
}

int MenuItem::Pos()
{
	return *pos;
}

void MenuItem::StrUpdate()
{
	int x_old = dx;
	int y_old = dy;
	int w_old = dw;
	int h_old = dh;
	Hide();
	ComputeStr();
	changed = 1;
	Update();
	x_old = (dx < x_old) ? dx : x_old;
	y_old = (dy < y_old) ? dy : y_old;
	w_old = (dw > w_old) ? dw : w_old;
	h_old = (dh > h_old) ? dh : h_old;
	SDL_UpdateRect(sdl.scr, x_old, y_old, w_old, h_old);
}

void MenuItem::EditStr(int code, int unicode)
{
	if (code == SDLK_BACKSPACE && min > 0) {
		//clear last char
		((char*)pos)[--min] = 0;
		StrUpdate();
	}
	else
		if (code >= 32 && code < 128 && min < max) {
			//letter
			((char*)pos)[min++] = unicode;
			StrUpdate();
		}
}

void MenuItem::SetRestrKeys(char *rk)
{
	restr_keys = rk;
}

void MenuItem::NoBackgnd()
{
	dw = -1;
}

int MenuItem::OnItem(int mx, int my)
{
    return (mx >= dx && mx < dx + dw && my >= dy && my <dy + dh);
}

int MenuItem::ButtonEvent(SDL_MouseButtonEvent button)
{
    if (type == ET_KEY) {
        *pos = 0;
        StrUpdate();
        return MR_CONTINUE;
    }
    int val = *pos;
    if (button.button == 3) {
		val -= step;
    	if (val < min)
   	        val = max - ((max - min) % step);
   	    used = 1;
	}	
	else
	    if (button.button == 1) {
			val += step;
			if (val > max) val = min;
       	    used = 1;
		}	
	if (val != *pos) {
		*pos = val;
		StrUpdate();
	}
	return MR_CONTINUE;
}

void MenuItem::SetString(char *s, int rep)
{
    strcpy(name, s);
    changed = 1;
    if (rep)
        StrUpdate();
    else
        ComputeStr();
}

void MenuItem::SetRange(int ll, int ul, int st, int rep)
{
    min = ll;
    max = ul;
    step = st;
    if (*pos > ul)
        *pos = ll;
    changed = 1;
    if (rep)
        StrUpdate();
}

int MenuItem::Used()
{
    int ret = used;
    used = 0;
    return ret;
}

void MenuItem::SetUsed(int u)
{
    used = u;
}
