/** PSP helper library ***************************************/
/**                                                         **/
/**                          menu.c                         **/
/**                                                         **/
/** This file contains a generic menu system                **/
/**                                                         **/
/** Copyright (C) Akop Karapetyan 2007                      **/
/**     You are not allowed to distribute this software     **/
/**     commercially. Please, notify me, if you make any    **/
/**     changes to this file.                               **/
/*************************************************************/
#include <malloc.h>
#include <string.h>

#include "menu.h"

static void _pspMenuDestroyItem(PspMenuItem* item);

PspMenu* pspMenuCreate()
{
  PspMenu* menu = (PspMenu*)malloc(sizeof(PspMenu));

  menu->Count = NULL;
  menu->First = NULL;
  menu->Last = NULL;

  return menu;
}

void pspMenuClear(PspMenu *menu)
{
  PspMenuItem *item, *next;

  for (item = menu->First; item; item = next)
  {
    next = item->Next;
    _pspMenuDestroyItem(item);
  }

  menu->Count = NULL;
  menu->First = NULL;
  menu->Last = NULL;
}

void pspMenuDestroy(PspMenu* menu)
{
  pspMenuClear(menu);
  free(menu);
}

PspMenuOption* pspMenuAppendOption(PspMenuItem *item, const char *text, const void *value, int select)
{
  PspMenuOption *option, *o;

  if (!(option=(PspMenuOption*)malloc(sizeof(PspMenuOption))))
    return NULL;

  if (!(option->Text=strdup(text)))
  {
    free(option);
    return NULL;
  }

  option->Value=value;
  option->Next=NULL;

  if (item->Options)
  {
    for (o=item->Options; o->Next; o=o->Next);
    o->Next=option;
    option->Prev=o;
  }
  else
  {
    item->Options=option;
    option->Prev=NULL;
  }

  if (select) item->Selected=option;

  return option;
}

void pspMenuSetCaption(PspMenuItem *item, const char *caption)
{
  if (item->Caption) free(item->Caption);
  item->Caption = (caption) ? strdup(caption) : NULL;
}

void pspMenuSelectOptionByValue(PspMenuItem *item, const void *value)
{
  PspMenuOption *option;

  for (option=item->Options; option; option=option->Next)
    if (option->Value == value)
    {
      item->Selected=option;
      return;
    }
}

void pspMenuModifyOption(PspMenuOption *option, const char *text, const void *value)
{
  free(option->Text);

  option->Text=NULL;
  option->Value=value;

  if (!(option->Text=strdup(text)))
    return;
}

void pspMenuClearOptions(PspMenuItem *item)
{
  PspMenuOption *option, *next;

  for (option=item->Options; option; option=next)
  {
    next=option->Next;
    free(option->Text);
    free(option);
  }

  item->Selected=NULL;
  item->Options=NULL;
}

PspMenuItem* pspMenuFindItemByUserdata(PspMenu *menu, const void *userdata)
{
  PspMenuItem *item;
  for (item=menu->First; item; item=item->Next)
    if (item->Userdata == userdata)
      return item;

  return NULL;
}

PspMenuItem* pspMenuGetNthItem(PspMenu *menu, int index)
{
  PspMenuItem *item;
  int i;

  for (item=menu->First, i=0; item; item=item->Next, i++)
    if (i == index) 
      return item;

  return NULL;
}

PspMenuItem* pspMenuAppendItem(PspMenu *menu, const char *caption, const void *userdata)
{
  PspMenuItem* item = (PspMenuItem*)malloc(sizeof(PspMenuItem));

  if (!item) return NULL;

  if (caption)
  {
    if (!(item->Caption = strdup(caption)))
    {
      free(item);
      return NULL;
    }
  }
  else item->Caption = NULL;

  item->Icon=NULL;
  item->Userdata=userdata;
  item->Options=NULL;
  item->Selected=NULL;
  item->Next=NULL;
  item->Prev=menu->Last;
  menu->Count++;

  if (menu->Last)
  {
    menu->Last->Next=item;
    menu->Last=item;
  }
  else menu->First=menu->Last=item;

  return item;
}

void _pspMenuDestroyItem(PspMenuItem* item)
{
  if (item->Caption)
    free(item->Caption);

  pspMenuClearOptions(item);

  free(item);
}
