/*
 * Copyright (c) 2006 Kazuaki ODA.
 * Copyright (c) 2006 Mode2 inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the company nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: ctr_webcomp.h 438 2006-11-11 15:09:48Z oda $
 */

#ifndef __CTR_WEBCOMP_H__
#define __CTR_WEBCOMP_H__

#include "apr_hash.h"
#include "apr_pools.h"
#include "apr_ring.h"
#include "apr_tables.h"
#include "apr_uri.h"

#define CTR_CLASS_NAME(_type)           _ctr_##_type##_t
#define CTR_WCONTAINER_CAST(_wc)        (&(_wc)->wcontainer)
#define CTR_WCOMP_CAST(_wc)             (&(_wc)->wcomp)
#define CTR_WCONTAINER_THIS(_wc)        ((_wc)->this)
#define CTR_WCOMP_THIS(_wcomp)          ((_wcomp)->this)

#define CTR_CLASS_DEF(_type)                                            \
    typedef struct _ctr_##_type CTR_CLASS_NAME(_type);                  \
    struct _ctr_##_type
#define CTR_WCOMP_MEMBER                ctr_wcomp_t wcomp
#define CTR_WCONTAINER_MEMBER           ctr_wcontainer_t wcontainer

#define CTR_VISITOR_MEMBER_NAME(_type)  _type##_visit
#define CTR_VISITOR_MEMBER_DEF(_type)                                   \
    apr_status_t (*_type##_visit)(CTR_CLASS_NAME(_type) *obj,           \
                                  const ctr_wcomp_visitor_t *vt,        \
                                  void *udata)

#define CTR_CHILD_INSERT_LAST(_cont, _child) do {                       \
    ctr_wcomp_t *_wcomp = CTR_WCOMP_CAST(_child);                       \
    if ((_cont)->last_child == NULL)                                    \
        (_cont)->children = _wcomp;                                     \
    else                                                                \
        (_cont)->last_child->next = _wcomp;                             \
    _wcomp->prev = (_cont)->last_child;                                 \
    (_cont)->last_child = _wcomp;                                       \
} while (0)

#define CTR_CHILD_INSERT_BEFORE(_listwcomp, _child) do {                \
    ctr_wcomp_t *_wcomp = CTR_WCOMP_CAST(_child);                       \
    _wcomp->prev = (_listwcomp)->prev;                                  \
    _wcomp->next = (_listwcomp);                                        \
    (_listwcomp)->prev = _wcomp;                                        \
    if (_wcomp->prev != NULL)                                           \
        _wcomp->prev->next = _wcomp;                                    \
    else                                                                \
        (_listwcomp)->parent->children = _wcomp;                        \
} while (0)

#define CTR_CHILD_INSERT_AFTER(_listwcomp, _child) do {                 \
    ctr_wcomp_t *_wcomp = CTR_WCOMP_CAST(_child);                       \
    _wcomp->prev = (_listwcomp);                                        \
    _wcomp->next = (_listwcomp)->next;                                  \
    (_listwcomp)->next = _wcomp;                                        \
    if (_wcomp->next != NULL)                                           \
        _wcomp->next->prev = _wcomp;                                    \
    else                                                                \
        (_listwcomp)->parent->last_child = _wcomp;                      \
} while (0)

#define CTR_FOREACH_CHILD(_wc, _wcont, _wcomp)                          \
    (_wcont) = CTR_WCONTAINER_CAST(_wc);                                \
    for ((_wcomp) = (_wcont)->children; (_wcomp) != NULL;               \
         (_wcomp) = (_wcomp)->next)
#define CTR_IS_CHILD_EMPTY(_wc)                                         \
    (&CTR_WCONTAINER_CAST(_wc)->children == NULL)

typedef struct _ctr_wcontainer ctr_wcontainer_t;
typedef struct _ctr_wcomp_visitor ctr_wcomp_visitor_t;
typedef struct _ctr_wcomp ctr_wcomp_t;
typedef struct _ctr_radio_info ctr_radio_info_t;
typedef enum _ctr_halign ctr_halign_t;
typedef enum _ctr_fontsize ctr_fontsize_t;
typedef enum _ctr_form_mtd ctr_form_mtd_t;
typedef enum _ctr_direct ctr_direct_t;
typedef enum _ctr_behav ctr_behav_t;
typedef enum _ctr_akey ctr_akey_t;
typedef enum _ctr_lang ctr_lang_t;
typedef enum _ctr_carrier ctr_carrier_t;
typedef enum _ctr_convmode ctr_convmode_t;
typedef enum _ctr_edit_style ctr_edit_style_t;
typedef enum _ctr_rawtype ctr_rawtype_t;

struct _ctr_wcontainer {
    void *this;
    ctr_wcontainer_t *parent;
    ctr_wcomp_t *children;
    ctr_wcomp_t *last_child;
    apr_pool_t *pool;
};

struct _ctr_wcomp {
    void *this;
    ctr_wcontainer_t *parent;
    ctr_wcomp_t *prev;
    ctr_wcomp_t *next;
    apr_status_t (*accept)(ctr_wcomp_t *wcomp, const ctr_wcomp_visitor_t *vt,
                           void *udata);
};

struct _ctr_radio_info {
    ctr_radio_info_t *siblings;
    int cnt;
    int chk;
    int cardno;
    int vno;
};

enum _ctr_halign {
    AL_NONE, AL_LEFT, AL_CENTER, AL_RIGHT
};

enum _ctr_fontsize {
    FS_NONE = 0, FS_XXSMALL, FS_XSMALL, FS_SMALL, FS_MEDIUM, FS_LARGE,
    FS_XLARGE, FS_XXLARGE
};

enum _ctr_form_mtd {
    FM_GET, FM_POST
};

enum _ctr_direct {
    DL_LEFT, DL_RIGHT
};

enum _ctr_behav {
    BH_SCROLL, BH_SLIDE, BH_ALTERNATE
};

enum _ctr_akey {
    AC_ZERO = 0, AC_ONE = 1, AC_TWO = 2, AC_THREE = 3, AC_FOUR = 4,
    AC_FIVE = 5, AC_SIX = 6, AC_SEVEN = 7, AC_EIGHT = 8, AC_NINE = 9,
    AC_ASTA = 10, AC_SHARP = 11, AC_NONE = 12
};

enum _ctr_lang {
    LG_IHTML   = 0x01,
    LG_IXHTML  = 0x02,
    LG_AUXHTML = 0x04,
    LG_SHTML   = 0x08,
    LG_SXHTML  = 0x10,
    LG_HDML    = 0x20,
    LG_WHTML   = 0x40,
    LG_FULL    = 0x80,
    LG_ALL     = 0xff
};

enum _ctr_carrier {
    CA_DOCOMO   = 0x01,
    CA_KDDI     = 0x02,
    CA_SOFTBANK = 0x04,
    CA_WILLCOM  = 0x08,
    CA_UNKNOWN  = 0x10,
    CA_ALL      = 0x1f
};

enum _ctr_convmode {
    CV_NONE = 0, CV_NORMAL, CV_WALLPAPER, CV_KP
};

enum _ctr_edit_style {
    ST_NONE = 0, ST_FULLKANA = 1, ST_HALFKANA = 2, ST_HALFALPHA = 3,
    ST_HALFNUM = 4
};

enum _ctr_rawtype {
    RT_INLINE, RT_BLOCK
};

CTR_CLASS_DEF(page) {
    CTR_WCONTAINER_MEMBER;
    const char *title;
    int bgcolor;
    int txtcolor;
    int txtcolor2;
    int lnkcolor;
};

CTR_CLASS_DEF(block) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
    ctr_halign_t align;
    int marquee;
    ctr_direct_t mqedirect;
    ctr_behav_t mqebehav;
    int mqeloop;
};

CTR_CLASS_DEF(form) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
    const apr_uri_t *act;
    ctr_form_mtd_t mtd;
    int utn;
    ctr_halign_t align;
    apr_hash_t *rdohash;
};

CTR_CLASS_DEF(heading) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
    int type;
    ctr_halign_t align;
};

CTR_CLASS_DEF(list) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
    int ordered;
};

CTR_CLASS_DEF(listitem) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
};

CTR_CLASS_DEF(deflist) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
};

CTR_CLASS_DEF(defterm) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
};

CTR_CLASS_DEF(defdesc) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
};

CTR_CLASS_DEF(deco) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
    int txtcolor;
    int txtcolor2;
    int bgcolor;
    ctr_fontsize_t fsize;
    int blink;
};

CTR_CLASS_DEF(anchor) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
    const apr_uri_t *href;
    ctr_akey_t akey;
    int utn;
};

CTR_CLASS_DEF(select) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
    const char *name;
};

CTR_CLASS_DEF(c3if) {
    CTR_WCOMP_MEMBER;
    CTR_WCONTAINER_MEMBER;
    ctr_lang_t lang;
    ctr_carrier_t carrier;
    const apr_table_t *names;
    const apr_table_t *groups;
    int isfoma;
    int istuka;
    int isxml;
    int not;
};

CTR_CLASS_DEF(hrline) {
    CTR_WCOMP_MEMBER;
    ctr_halign_t align;
    int size;
    const char *width;
    int color;
};

CTR_CLASS_DEF(newline) {
    CTR_WCOMP_MEMBER;
};

CTR_CLASS_DEF(image) {
    CTR_WCOMP_MEMBER;
    apr_uri_t *src;
    const char *alt;
    ctr_convmode_t cvmode;
    int percent;
    int copy;
    int mframe;
};

CTR_CLASS_DEF(editbox) {
    CTR_WCOMP_MEMBER;
    const char *name;
    const char *val;
    int size;
    int max;
    ctr_edit_style_t style;
};

CTR_CLASS_DEF(passwd) {
    CTR_WCOMP_MEMBER;
    const char *name;
    const char *val;
    int size;
    int max;
};

CTR_CLASS_DEF(radio) {
    CTR_WCOMP_MEMBER;
    const char *name;
    const char *val;
    int chk;
    ctr_radio_info_t *rinfo;
    int no;
};

CTR_CLASS_DEF(chkbox) {
    CTR_WCOMP_MEMBER;
    const char *name;
    const char *val;
    int chk;
};

CTR_CLASS_DEF(hidden) {
    CTR_WCOMP_MEMBER;
    const char *name;
    const char *val;
};

CTR_CLASS_DEF(submit) {
    CTR_WCOMP_MEMBER;
    const char *name;
    const char *val;
};

CTR_CLASS_DEF(reset) {
    CTR_WCOMP_MEMBER;
    const char *name;
    const char *val;
};

CTR_CLASS_DEF(option) {
    CTR_WCOMP_MEMBER;
    const char *val;
    int sel;
    const char *txt;
};

CTR_CLASS_DEF(textarea) {
    CTR_WCOMP_MEMBER;
    const char *name;
    int rows;
    int cols;
    ctr_edit_style_t style;
    const char *txt;
};

CTR_CLASS_DEF(text) {
    CTR_WCOMP_MEMBER;
    const char *txt;
};

CTR_CLASS_DEF(emoji) {
    CTR_WCOMP_MEMBER;
    const char *id;
};

CTR_CLASS_DEF(rawtext) {
    CTR_WCOMP_MEMBER;
    ctr_rawtype_t type;
    const char *txt;
};

CTR_CLASS_DEF(brank) {
    CTR_WCOMP_MEMBER;
};

struct _ctr_wcomp_visitor {
    CTR_VISITOR_MEMBER_DEF(page);
    CTR_VISITOR_MEMBER_DEF(block);
    CTR_VISITOR_MEMBER_DEF(form);
    CTR_VISITOR_MEMBER_DEF(heading);
    CTR_VISITOR_MEMBER_DEF(list);
    CTR_VISITOR_MEMBER_DEF(listitem);
    CTR_VISITOR_MEMBER_DEF(deflist);
    CTR_VISITOR_MEMBER_DEF(defterm);
    CTR_VISITOR_MEMBER_DEF(defdesc);
    CTR_VISITOR_MEMBER_DEF(deco);
    CTR_VISITOR_MEMBER_DEF(anchor);
    CTR_VISITOR_MEMBER_DEF(select);
    CTR_VISITOR_MEMBER_DEF(c3if);
    CTR_VISITOR_MEMBER_DEF(hrline);
    CTR_VISITOR_MEMBER_DEF(newline);
    CTR_VISITOR_MEMBER_DEF(image);
    CTR_VISITOR_MEMBER_DEF(editbox);
    CTR_VISITOR_MEMBER_DEF(passwd);
    CTR_VISITOR_MEMBER_DEF(radio);
    CTR_VISITOR_MEMBER_DEF(chkbox);
    CTR_VISITOR_MEMBER_DEF(hidden);
    CTR_VISITOR_MEMBER_DEF(submit);
    CTR_VISITOR_MEMBER_DEF(reset);
    CTR_VISITOR_MEMBER_DEF(option);
    CTR_VISITOR_MEMBER_DEF(textarea);
    CTR_VISITOR_MEMBER_DEF(text);
    CTR_VISITOR_MEMBER_DEF(emoji);
    CTR_VISITOR_MEMBER_DEF(rawtext);
    CTR_VISITOR_MEMBER_DEF(brank);
};

CTR_CLASS_NAME(page) *ctr_page_new(apr_pool_t *pool, const char *title,
                                   int bgcolor, int txtcolor, int txtcolor2,
                                   int lnkcolor);
CTR_CLASS_NAME(block) *ctr_block_new(ctr_wcontainer_t *cont,
                                     ctr_halign_t align, int marquee,
                                     ctr_direct_t mqedirect,
                                     ctr_behav_t mqebehav, int mqeloop);
CTR_CLASS_NAME(form) *ctr_form_new(ctr_wcontainer_t *cont,
                                   const apr_uri_t *act, ctr_form_mtd_t mtd,
                                   int utn, ctr_halign_t align);
CTR_CLASS_NAME(heading) *ctr_heading_new(ctr_wcontainer_t *cont, int type,
                                         ctr_halign_t align);
CTR_CLASS_NAME(list) *ctr_list_new(ctr_wcontainer_t *cont, int ordered);
CTR_CLASS_NAME(listitem) *ctr_listitem_new(ctr_wcontainer_t *cont);
CTR_CLASS_NAME(deco) *ctr_deco_new(ctr_wcontainer_t *cont, int txtcolor,
                                   int txtcolor2, int bgcolor,
                                   ctr_fontsize_t fsize, int blink);
CTR_CLASS_NAME(deflist) *ctr_deflist_new(ctr_wcontainer_t *cont);
CTR_CLASS_NAME(defterm) *ctr_defterm_new(ctr_wcontainer_t *cont);
CTR_CLASS_NAME(defdesc) *ctr_defdesc_new(ctr_wcontainer_t *cont);
CTR_CLASS_NAME(anchor) *ctr_anchor_new(ctr_wcontainer_t *cont,
                                       const apr_uri_t *href, ctr_akey_t akey,
                                       int utn);
CTR_CLASS_NAME(select) *ctr_select_new(ctr_wcontainer_t *cont,
                                       const char *name);
CTR_CLASS_NAME(c3if) *ctr_c3if_new(ctr_wcontainer_t *cont, ctr_lang_t lang,
                                   ctr_carrier_t carrier,
                                   const apr_table_t *names,
                                   const apr_table_t *groups,
                                   int isfoma, int istuka, int isxml, int not);
CTR_CLASS_NAME(hrline) *ctr_hrline_new(ctr_wcontainer_t *cont,
                                       ctr_halign_t align, int size,
                                       const char *width, int color);
CTR_CLASS_NAME(newline) *ctr_newline_new(ctr_wcontainer_t *cont);
CTR_CLASS_NAME(image) *ctr_image_new(ctr_wcontainer_t *cont,
                                     apr_uri_t *src, const char *alt,
                                     ctr_convmode_t cvmode, int percent,
                                     int copy, int mframe);
CTR_CLASS_NAME(editbox) *ctr_editbox_new(ctr_wcontainer_t *cont,
                                         const char *name, const char *val,
                                         int size, int max,
                                         ctr_edit_style_t style);
CTR_CLASS_NAME(passwd) *ctr_passwd_new(ctr_wcontainer_t *cont,
                                       const char *name, const char *val,
                                       int size, int max);
CTR_CLASS_NAME(radio) *ctr_radio_new(ctr_wcontainer_t *cont, const char *name,
                                     const char *val, int chk,
                                     ctr_radio_info_t *rinfo, int no);
CTR_CLASS_NAME(chkbox) *ctr_chkbox_new(ctr_wcontainer_t *cont,
                                       const char *name, const char *val,
                                       int chk);
CTR_CLASS_NAME(hidden) *ctr_hidden_new(ctr_wcontainer_t *cont,
                                       const char *name, const char *val);
CTR_CLASS_NAME(submit) *ctr_submit_new(ctr_wcontainer_t *cont,
                                       const char *name, const char *val);
CTR_CLASS_NAME(reset) *ctr_reset_new(ctr_wcontainer_t *cont, const char *name,
                                     const char *val);
CTR_CLASS_NAME(option) *ctr_option_new(ctr_wcontainer_t *cont,
                                       const char *val, int sel,
                                       const char *txt);
CTR_CLASS_NAME(textarea) *ctr_textarea_new(ctr_wcontainer_t *cont,
                                           const char *name, int rows,
                                           int cols, ctr_edit_style_t style,
                                           const char *txt);
CTR_CLASS_NAME(text) *ctr_text_new(ctr_wcontainer_t *cont, const char *s);
CTR_CLASS_NAME(emoji) *ctr_emoji_new(ctr_wcontainer_t *cont, const char *id);
CTR_CLASS_NAME(rawtext) *ctr_rawtext_new(ctr_wcontainer_t *cont,
                                         ctr_rawtype_t type, const char *s);
CTR_CLASS_NAME(brank) *ctr_brank_new(ctr_wcontainer_t *cont);

#endif  /* __CTR_WEBCOMP_H__ */
