/*--------------------------------------------------------------------------
  Project:  Manual 2D Library - m2d
  File:     manualTocPanel.h

  Copyright (C)2007-2009 Nintendo  All Rights Reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law. They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Revision: 1758 $
 *-------------------------------------------------------------------------*/

#ifndef NTMV_M2D_MANUALTOCPANEL_H_
#define NTMV_M2D_MANUALTOCPANEL_H_

#if _MSC_VER > 1000 || defined(__CWCC__)
#pragma once
#endif

#include <ntmv/m2d/types.h>
#include <ntmv/m2d/uiElement.h>
#include <ntmv/m2d/manualButton.h>
#include <ntmv/m2d/uiPanel.h>

struct NNSG2dFont;

namespace ntmv
{
namespace m2d
{

struct TouchPanelData;
class ObjectConstructor;
class ObjButton;
class UIStatic;
class ScrollButton;
class ManualTableOfContents;
class ManualHeader;
class SoundManager;

/*
    Event types for the control panel on the Contents page
*/
enum
{
    MANUALTOCEVENT_NONE,                    // No event
    MANUALTOCEVENT_EXIT,                    // Exit Manual Viewer
    MANUALTOCEVENT_OPENCLOSE,               // The display switched between shown and hidden
    MANUALTOCEVENT_HELPPAGESELECTED,        // The button for the Help page was pressed
    MANUALTOCEVENT_HEADERSELECTCHANGED,     // The selected header changed
    MANUALTOCEVENT_CHAPTERSELECTCHANGED,    // The selected section changed

    MANUALTOCEVENT_MAX
};

enum
{
    MANUALTOCDISPSTATE_CLOSED,
    MANUALTOCDISPSTATE_OPENED,

    MANUALTOCDISPSTATE_MAX
};

enum
{
    MANUALTOCHELPSTATE_UNSELECTED,
    MANUALTOCHELPSTATE_SELECTED,

    MANUALTOCHELPSTATE_MAX
};

/*
    Structure that shows the selection state for the Contents page
*/
struct ManualTocTouchResult
{
    u16             eventType;  // Event
    u16             state;      // Status
};

namespace detail
{

enum
{
    BUTTON_HELP,
    BUTTON_EXIT,
    BUTTON_DISP,
    BUTTON_PREV,
    BUTTON_NEXT,

    BUTTON_MAX,

    TOP_PANEL_BACK  = BUTTON_MAX,
    BTM_PANEL_BACK,

    HEADRETCOVER,                       // Transparent area for returning to the header display
    CHAPRETCOVER,                       // Transparent area for returning to the section display

    UI_MAX
};

const int   HEADER_DISP_MAX = 5;            // Maximum number of headers that are displayed at once

// Maximum number of headers and sections that are displayed at once
const int   TOC_ITEM_DISP_MAX           =
                    HEADER_DISP_MAX > CHAPTER_ITEM_DISP_MAX ?
                        HEADER_DISP_MAX:
                        CHAPTER_ITEM_DISP_MAX;

const int   TOC_ITEM_PAGE_BUTTON_NUM    = 2;    // Number of page skip buttons to use when a header or section is divided into multiple pages
                                                // 

const int   TOC_ITEM_MASK_NUM           = 2;    // Number of mask objects for headers and sections

enum
{
    TOC_ELEMENT_PAGE_BUTTON_ID  = 0,

    TOC_ELEMENT_PAGE_BACK_ID    = TOC_ITEM_PAGE_BUTTON_NUM,

    TOC_ELEMENT_BUTTON_ID       = TOC_ELEMENT_PAGE_BACK_ID + TOC_ITEM_MASK_NUM
};

enum
{
    ITEMS_PANEL_HEADER,
    ITEMS_PANEL_CHAPTER,

    ITEMS_PANEL_MAX
};

enum
{
    ITEMVIEWMODE_HEADER,
    ITEMVIEWMODE_CHAPTER,
    ITEMVIEWMODE_HEADERONLY,

    ITEMVIEWMODE_MAX
};

/*
    Control panel text
*/
enum
{
    CTRLPANELTEXT_CLOSE,            // Close the manual
    CTRLPANELTEXT_PREVPAGE,         // Previous page
    CTRLPANELTEXT_NEXTPAGE,         // Next page

    CTRLPANELTEXT_MAX
};

struct ItemsPanelData;

class ItemsPanel : public UIPanel
{
    typedef UIPanel Base;

public:
    struct UpdateResult
    {
                        UpdateResult()
                        :   bPageChanged(false),
                            bSelectChanged(false),
                            bClicked(false)
                        {}

        bool            bPageChanged;   // Did the page change?
        bool            bSelectChanged; // Did the selected item change?
        bool            bClicked;       // Was an item clicked?
                                        // (this is unrelated to whether it changed)
        bool            bTouchOn;       // Was the Touch Panel tapped?
        bool            bEnabled;       // Was a valid target tapped?
    };

    struct DrawTextInfo
    {
        const wchar_t*  text;
        bool            bArrow;
    };

    typedef const DrawTextInfo
                        DrawHeaderTextCallback(
                            void*   userData,
                            s16     headerIdx);

                        ItemsPanel();

    void                Init(
                            const ObjectConstructor&    objectConstructor,
                            ObjManager*                 pObjManager,
                            const NNSG2dFont *const     fonts[],
                            const ItemsPanelData&       data);

    virtual void        Finalize(const ObjectConstructor& objectConstructor);

    void                InitPage(u16 itemNum);

    u16                 GetItemDispMax() const      { return mItemDispMax; }    // Maximum number of header buttons to display

    s16                 GetItemStartIdx() const     { return mItemStartIdx; }

    s16                 GetSelectedItemIdx() const  { return mSelectedItemIdx; }

    bool                SetSelectedItemIdx(s16 newSelectedItemIdx);

    bool                EnsureSelectedItemVisible();

    bool                TestTouchPanel(
                            UpdateResult*           pUpdateResult,
                            const TouchPanelData&   tpData);

    void                DrawHeaderButtonText(
                            const DrawTextInfo  drawTextInfoAry[],
                            u16                 textNum,
                            s16                 startHeaderIdx);

    void                DrawHeaderButtonText(
                            const DrawTextInfo& drawTextInfo,
                            s16                 headerIdx);

    void                DrawChapterButtonText(
                            const DrawTextInfo  drawTextInfoAry[],
                            u16                 textNum,
                            s16                 startChapterIdx);

    void                SetUI(
                            u16         index,
                            UIElement*  uiElement);

    bool                IsBusy() const      { return mBtnScrlPos != mBtnScrlEndPos; }

    bool                AnimateHeader(
                            DrawHeaderTextCallback  cb,
                            void*                   userData);

    u16                 GetItemAllocNum() const     { return static_cast<u16>(mItemDispMax + 1); }

    void                UpdateItemButtonState(bool bChecked);

    bool                IsFocused() const           { return mFocused; }

    void                SetFocused(bool value)      { mFocused = value; }

private:
    void                InitPageButton();

    void                SetTocPageIdx(s16 tocPageIdx);

    bool                ChangeTocPageIdx(s16 tocPageIdx);

    void                UpdatePageButton();

    s16                 GetPointedButtonIdx(Point point) const;

    u16                 GetBaseElementNum() const
    {
        return static_cast<u16>(TOC_ITEM_PAGE_BUTTON_NUM + TOC_ITEM_MASK_NUM + GetItemAllocNum());
    }

    const NNSG2dFont *const *
                        mFonts;

    u16                 mItemNum;
    s16                 mItemStartIdx;          // Starting header index for header buttons
    u16                 mItemDispMax;           // Maximum number of header buttons to display
    s16                 mTocPageIdx;            // Header page index
    u16                 mTocPageMax;            // Maximum number of header button pages
    s16                 mSelectedItemIdx;       // Index to the selected header
    s16                 mPointedButtonIdx;

    ManualButton**      mItemBtns;
    s16*                mDrawTextIdx;
    s16                 mBtnScrlPos;
    s16                 mBtnScrlEndPos;

    bool                mFocused;
};

}   // namespace detail

/*
    UI class to display for the manual's Contents page
*/
class ManualTocPanel : public UIElement
{
    typedef UIElement   Base;

public:
                        ManualTocPanel();

    void                Init(
                            const ObjectConstructor&    objectConstructor,
                            ObjManager*                 pObjManager,
                            const NNSG2dFont *const     fonts[],
                            s16                         pagePrevButtonW,
                            const wchar_t*              ctrlPanelTexts[],
                            SoundManager*               pSndMgr);

    virtual void        Finalize(const ObjectConstructor& objectConstructor);

    virtual void        Draw(
                            const ObjG2dInfo&   info,
                            Point               parentPos);

    void                SetupManualTableOfContents(ManualTableOfContents* pManToc);

    bool                HasManualToc() const    { return 0 != mpManualToc; }

    bool                TestTouchPanel(
                            ManualTocTouchResult*   pManualTocTouchResult,
                            const TouchPanelData&   tpData);

    u16                 MovePrevItem();

    u16                 MoveNextItem();

    bool                PressHelpButton(bool* pbHelpSelected);

    bool                PressTocOpenButton();

    void                PressExitButton();

    const ManualHeader* GetSelectedHeader() const;

    s16                 GetSelectedHeaderIdx() const;

    void                SetSelectedHeaderIdx(s16 value);

    s16                 GetSelectedChapterIdx() const;

    void                SetSelectedChapterIdx(s16 value);

    ScrollButton*       GetScrollButton() const { return mScrollButton; }

    bool                IsOpened() const        { return mbOpening; }

    bool                IsBusy() const;

    void                Animate();

    void                TransferBGDataToHW();

private:
    void                DrawHeaderButtonText();

    void                DrawChapterButtonText();

    void                InitChapterPage();

    void                SetNextPrevItemButtonState(
                            bool bEnablePrev,
                            bool bEnableNext);

    void                UpdateNextPrevItemButtonState();

    bool                HitTestCtrlPanel(
                            ManualTocTouchResult*   pResult,
                            const TouchPanelData&   tpData);

    void                SetOpened(bool value);

    void                SetItemViewMode(u16 mode);

    void                UpdateItemViewMode(
                            bool            bSelectPage     = false
                        );

    void                SetHelpButtonSelected(bool bSelected);

    void                SetScrollIndicatorPosX();

    bool                PressHelpButton();

    ManualTableOfContents*
                        mpManualToc;

    ObjManager*         mpObjManager;
    SoundManager*       mpSndMgr;
    UIPanel             mWholePanel;
    UIPanel             mBtmPanel;

    UIPanel*            mItemsPanel;
    detail::ItemsPanel* mItemsPanels[detail::ITEMS_PANEL_MAX];
    UIElement*          mHitItems[detail::UI_MAX];
    UIStatic*           mManualItemBack;
    UIElement*          mHeadRetCover;
    UIElement*          mChapRetCover;
    ScrollButton*       mScrollButton;
    s16                 mPointedUIIdx;
    s16                 mHScrollTargetPos;
    u16                 mItemViewMode;
    s16                 mTocIndScrollTargetPos;

    Point               mBgPoss[3];

    bool                mbHelpSelected;
    bool                mbOpening;
    bool                mbDispItemBack;
};

}   // namespace m2d
}   // namespace ntmv

/* NTMV_M2D_MANUALTOCPANEL_H_ */
#endif
