#include "MenuSystem.h"
#include "Resource.h"
#include "Keyboard.h"
#include <string>

CXMenuSystem::CXMenuSystem(CXxPad *_parent, DWORD _outlinecolour, DWORD _innercolour, DWORD _fontcolour)
{
	parent = _parent;
	outlinecolour = _outlinecolour;
	innercolor = _innercolour;
	fontcolour = _fontcolour;

}

HRESULT CXMenuSystem::Initialize()
{
  curMainMenu = -1;
  curMenuLine = 0;

  lastMenuRect.left = 0;
  lastMenuRect.top = 0;
  lastMenuRect.bottom = 0;
  lastMenuRect.right = 0;
  lastAlphaValue = 0x00000000;


  m_check = parent->m_xprResource.GetTexture( resource_MenuCheck_OFFSET );
  
  return S_OK;
}

HRESULT CXMenuSystem::Render()
{
  RenderMainMenuItems();

  // Draw menus if we are in that mode.
  if (curMainMenu >= 0)
  {
    // Draw the menu selecter, then the menu, then the menu item selector.
    RenderSubMenuItems(MENU_ITEM_SELECT);
  }

  // Render any fadeouts.
  if (lastAlphaValue > 0)
  {
    parent->DrawRectWithBorder( lastMenuRect.left, lastMenuRect.top, lastMenuRect.right, lastMenuRect.bottom, lastAlphaValue | 0x000A246A, lastAlphaValue | 0x000A246A, lastAlphaValue | 0x000A246A);
    lastAlphaValue -= 0x06000000;
  }
  return S_OK;
}

HRESULT CXMenuSystem::Cleanup()
{
  return S_OK;
}

HRESULT CXMenuSystem::FrameMove()
{

  // Only move Cursor Right if we need to.
  if ( BeginCursorUpRepeat() )
    MoveCursorUp();
  
  // Only move Cursor Right if we need to.
  if ( BeginCursorDownRepeat() )
    MoveCursorDown();

  // Only move Cursor Right if we need to.
  if ( BeginCursorLeftRepeat() )
    MoveCursorLeft();

  // Only move Cursor Right if we need to.
  if ( BeginCursorRightRepeat() )
    MoveCursorRight();

  

  if( parent->GetGamePad()->bPressedAnalogButtons[XINPUT_GAMEPAD_B] || parent->GetGamePad()->wPressedButtons & XINPUT_GAMEPAD_BACK || parent->lastKBChar == KEY_ESC)
  {
    curMainMenu = -1;
    curMenuLine = 0;
    parent->curMode = parent->Mode::MODE_NORMAL;
  }


  // Call the function of the menu item.
  // If null ignore
  lastItemId = 0;
  if( parent->GetGamePad()->bPressedAnalogButtons[XINPUT_GAMEPAD_A] || parent->lastKBChar == KEY_ENTER)
  {
    // Iterator is used to loop through the vector.
    subItems::iterator subItemIterator;

    int curSubItemIndex = 0;
    for (subItemIterator = menuSubItems.begin(); subItemIterator != menuSubItems.end(); subItemIterator++)
    {
      if ((*subItemIterator).parent == curMainMenu)
      {
        if (curMenuLine == curSubItemIndex)
        {
          lastAlphaValue = 0x60000000;

          // Only allow this command to get reported if the items is enabled.
          if ((*subItemIterator).enabled)
            lastItemId = (*subItemIterator).itemId;
          else
            lastItemId = -1;
          break;
        }

        curSubItemIndex++;
      }
    }
  }

  return S_OK;
}

void CXMenuSystem::AddMenuItem(string name)
{
  menuMainItems.push_back(name);
}

void CXMenuSystem::AddSubMenuItem(MENUSUBITEM subItem)
{
  menuSubItems.push_back(subItem);
}


void CXMenuSystem::RenderMainMenuItems()
{
  // Iterator is used to loop through the vector.
  mainItems::iterator theIterator;
  
  // Now copy all the data read into the fileContents structure, breaking at new lines
  FLOAT lastX = 34;
  for (theIterator = menuMainItems.begin(); theIterator != menuMainItems.end(); theIterator++)
  {
    WCHAR wcmenuItem[256];
    const char* pmenuItem = (*theIterator).c_str();
    mbsrtowcs(wcmenuItem, &pmenuItem, 256, NULL);
 	  parent->m_Font.DrawText(lastX, 68, 0xfffff600, wcmenuItem);

    FLOAT width = 0;
    FLOAT height = 0;
    parent->m_Font.GetTextExtent(wcmenuItem, &width, &height, FALSE);
    lastX += width + 12;
  }


}

void CXMenuSystem::DrawDropShadow(fRECT srcRect)
{
  parent->DrawRectWithBorder( srcRect.left + 3, srcRect.top + 5, 
                              srcRect.right + 3, srcRect.bottom + 5, 
                              MENU_SHADOW, MENU_SHADOW, MENU_SHADOW);

  parent->DrawRectWithBorder( srcRect.left + 4, srcRect.top + 4, 
                              srcRect.right + 4, srcRect.bottom + 4, 
                              MENU_SHADOW, MENU_SHADOW, MENU_SHADOW);

  parent->DrawRectWithBorder( srcRect.left + 5, srcRect.top + 3, 
                              srcRect.right + 5, srcRect.bottom + 3, 
                              MENU_SHADOW, MENU_SHADOW, MENU_SHADOW);
}

void CXMenuSystem::RenderSubMenuItems(DWORD color)
{
  // Now copy all the data read into the fileContents structure, breaking at new lines
  FLOAT curX = 34;
  int curInc = 0;
  // Iterator is used to loop through the main menu items
  mainItems::iterator menuMainItemsIterator;
  subItems::iterator menuSubItemsIterator;

  for (menuMainItemsIterator = menuMainItems.begin(); menuMainItemsIterator != menuMainItems.end(); menuMainItemsIterator++)
  {
    FLOAT width = 0;
    FLOAT height = 0;
    WCHAR wcmenuItem[256];
    const char* pmenuItem = (*menuMainItemsIterator).c_str();
    mbsrtowcs(wcmenuItem, &pmenuItem, 256, NULL);
    parent->m_Font.GetTextExtent(wcmenuItem, &width, &height, FALSE);
    if (curInc == curMainMenu)
    {
      // Draw the Menu Seector
      parent->DrawRectWithBorder( curX - MENU_MARGIN_SIZE, 66, curX + width + MENU_MARGIN_SIZE, 91, MENU_MAIN_SELECT, MENU_MAIN_SELECT, COLOUR_BLUE);

      FLOAT maxWidth = GetMaxWidthOfSubItems(curMainMenu);
      FLOAT totalHeight = GetTotalHeightOfSubItems(curMainMenu);
      FLOAT curY = 94;
      fRECT menuRect;
      menuRect.top = curY;
      menuRect.left = curX - MENU_MARGIN_SIZE;
      menuRect.right = menuRect.left + MENU_MARGIN_SIZE + MENU_MARGIN_SIZE + MENU_IMAGE_SIZE + maxWidth + MENU_IMAGE_SIZE + MENU_MARGIN_SIZE;
      menuRect.bottom = menuRect.top + totalHeight;
      // Draw the drop shadow
      DrawDropShadow(menuRect);
      // Draw the underlying menu box and border
      parent->DrawRectWithBorder( menuRect.left, menuRect.top, menuRect.right, menuRect.bottom, COLOUR_LIGHTBLUE, COLOUR_LIGHTBLUE, COLOUR_BLUE);

      // Need to loop thru all the sub items, and draw them.
      int curSubInc = 0;
      for (menuSubItemsIterator = menuSubItems.begin(); menuSubItemsIterator != menuSubItems.end(); menuSubItemsIterator++)
      {
        if ((*menuSubItemsIterator).parent == curMainMenu)
        {
          DWORD curColor;
          if ((*menuSubItemsIterator).enabled)
            curColor = 0xff000000;
          else
            curColor = 0xff888888;

          parent->m_Font.DrawText(curX + MENU_MARGIN_SIZE + MENU_IMAGE_SIZE, curY  + (curSubInc * 25) , curColor, (*menuSubItemsIterator).name.c_str());

          if ((*menuSubItemsIterator).checked)
          {
            D3DXVECTOR4 curImg;
            curImg.x = curX + MENU_MARGIN_SIZE;
            curImg.z = curImg.x + 15;
            curImg.y = curY + (curSubInc * 25) + MENU_MARGIN_SIZE;
            curImg.w = curImg.y + 15;

            parent->RenderImage (curImg, m_check, 1.0f, 0.0f, 0.0f);
          }

          curSubInc++;
        }
        //parent->m_Font.DrawText(curX, curY, 0xff000000, L"New\nOpen...\nSave\nSave As...\nExit");
      }
      
      // Draw the current Y pos selector
      curY += (curMenuLine * 25);
      parent->DrawRectWithBorder( menuRect.left + 1, curY, menuRect.right - 1, curY + 25, color, color, COLOUR_BLUE);
      lastMenuRect.left = menuRect.left + 1;
      lastMenuRect.top = curY;
      lastMenuRect.right = menuRect.right - 1;
      lastMenuRect.bottom = curY + 25;

      break;
    }

    // increment the current xpos all the time.
    curX += width + 10;
    curInc++;
  }
  
}

FLOAT CXMenuSystem::GetMaxWidthOfSubItems(int parent_id)
{

  // Iterator is used to loop through the vector.
  subItems::iterator theIterator;
  
  // Now copy all the data read into the fileContents structure, breaking at new lines
  FLOAT maxWidth = 0;
  for (theIterator = menuSubItems.begin(); theIterator != menuSubItems.end(); theIterator++)
  {
    if ((*theIterator).parent == parent_id)
    {
      // wcmenuItem[256];
      const wchar_t * pmenuItem = (*theIterator).name.c_str();
      //mbsrtowcs(wcmenuItem, &pmenuItem, 256, NULL);
      FLOAT width = 0;
      FLOAT height = 0;
      parent->m_Font.GetTextExtent(pmenuItem, &width, &height, FALSE);
      if (width > maxWidth)
        maxWidth = width;
    }
  }

  return maxWidth;
}

FLOAT CXMenuSystem::GetTotalHeightOfSubItems(int parent_id)
{
  // Iterator is used to loop through the vector.
  subItems::iterator theIterator;
  
  // Now copy all the data read into the fileContents structure, breaking at new lines
  FLOAT totHeight = 0;
  for (theIterator = menuSubItems.begin(); theIterator != menuSubItems.end(); theIterator++)
  {
    if ((*theIterator).parent == parent_id)
    {
      //WCHAR wcmenuItem[256];
      const wchar_t * pmenuItem = (*theIterator).name.c_str();
      //mbsrtowcs(wcmenuItem, &pmenuItem, 256, NULL);
      FLOAT width = 0;
      FLOAT height = 0;
      parent->m_Font.GetTextExtent(pmenuItem, &width, &height, FALSE);
      totHeight += height;
    }
  }
  
  return totHeight;
}

int CXMenuSystem::GetSubItemCountForParent(int parent_id)
{
  int count = 0;
  // Iterator is used to loop through the vector.
  subItems::iterator menuSubItemsIterator;

  for (menuSubItemsIterator = menuSubItems.begin(); menuSubItemsIterator != menuSubItems.end(); menuSubItemsIterator++)
  {
    if ((*menuSubItemsIterator).parent == parent_id)
    {
      count++;
    }
  }
  return count;
}

void CXMenuSystem::ResetMenu()
{
  curMainMenu = -1;
  curMenuLine = 0;
}

int CXMenuSystem::GetLastItemId()
{
  return lastItemId;
}

void CXMenuSystem::MoveCursorUp(int count)
{
  if (curMenuLine >0)
    curMenuLine--;
  else
    curMenuLine = GetSubItemCountForParent(curMainMenu) - 1;
}

void CXMenuSystem::MoveCursorDown(int count)
{
  if (curMenuLine < (GetSubItemCountForParent(curMainMenu) - 1))
    curMenuLine++;
  else
    curMenuLine = 0;
}

void CXMenuSystem::MoveCursorLeft(int count)
{
  if (curMainMenu > 0)
    curMainMenu--;
  else
    curMainMenu = (int)menuMainItems.size() - 1;
  curMenuLine = 0;
}

void CXMenuSystem::MoveCursorRight(int count)
{
  if (curMainMenu < (int)menuMainItems.size() - 1)
    curMainMenu++;
  else
    curMainMenu = 0;
  curMenuLine = 0;
}

bool CXMenuSystem::BeginCursorUpRepeat()
{
  static DWORD starttime=0;
  static DWORD delay=0;
  if( parent->GetGamePad()->wLastButtons & XINPUT_GAMEPAD_DPAD_UP || parent->lastKBChar == KEY_UP)
  {
    if (!movingUp)
    {
      movingUp=true;
      starttime=timeGetTime();
      delay=200;
      return true;
    }
    else
    {
      // is pressed here
      if (timeGetTime()>starttime+delay)
      {
        starttime=timeGetTime();
        delay=50;
        return true;
      }
    }
  }
  else
  {
    movingUp=false;
  }
  return false;
}

bool CXMenuSystem::BeginCursorDownRepeat()
{
  static DWORD starttime=0;
  static DWORD delay=0;
  if( parent->GetGamePad()->wLastButtons & XINPUT_GAMEPAD_DPAD_DOWN || parent->lastKBChar == KEY_DOWN)
  {
    if (!movingDown)
    {
      movingDown=true;
      starttime=timeGetTime();
      delay=200;
      return true;
    }
    else
    {
      if (timeGetTime()>starttime+delay)
      {
        starttime=timeGetTime();
        delay=50;
        return true;
      }
    }
  }
  else
  {
    movingDown=false;
  }
  
  return false;
}

bool CXMenuSystem::BeginCursorLeftRepeat()
{
  static DWORD starttime=0;
  static DWORD delay=0;
  if( parent->GetGamePad()->wLastButtons & XINPUT_GAMEPAD_DPAD_LEFT || parent->lastKBChar == KEY_LEFT)
  {
    if (!movingLeft)
    {
      movingLeft=true;
      starttime=timeGetTime();
      delay=200;
      return true;
    }
    else
    {
      // is pressed here
      if (timeGetTime()>starttime+delay)
      {
        starttime=timeGetTime();
        delay=50;
        return true;
      }
    }
  }
  else
  {
    movingLeft=false;
  }
  
  return false;
}

bool CXMenuSystem::BeginCursorRightRepeat()
{
  static DWORD starttime=0;
  static DWORD delay=0;
  if( parent->GetGamePad()->wLastButtons & XINPUT_GAMEPAD_DPAD_RIGHT || parent->lastKBChar == KEY_RIGHT)
  {
    if (!movingRight)
    {
      movingRight=true;
      starttime=timeGetTime();
      delay=200;
      return true;
    }
    else
    {
      // is pressed here
      if (timeGetTime()>starttime+delay)
      {

        starttime=timeGetTime();
        delay=50;
        return true;
      }
    }
  }
  else
  {
    movingRight=false;
  }
  return false;
}


MENUSUBITEM* CXMenuSystem::GetSubItemFromId(int itemId)
{
  // Iterator is used to loop through the vector.
  subItems::iterator menuSubItemsIterator;

  for (menuSubItemsIterator = menuSubItems.begin(); menuSubItemsIterator != menuSubItems.end(); menuSubItemsIterator++)
  {
    if ((*menuSubItemsIterator).itemId == itemId)
    {
      return &(*menuSubItemsIterator);
    }
  }
  return NULL;
}