/*
 * 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.c 436 2006-11-11 08:52:58Z oda $
 */

#include "ctr_webcomp.h"

#define CTR_WCONTAINER_INIT(_wc, _parent, _pool) do {                   \
    ctr_wcontainer_t *_wcont = CTR_WCONTAINER_CAST(_wc);                \
    _wcont->this = (_wc);                                               \
    _wcont->parent = (_parent);                                         \
    _wcont->children = NULL;                                            \
    _wcont->last_child = NULL;                                          \
    _wcont->pool = (_pool);                                             \
} while(0)

#define CTR_WCOMP_INIT(_wc, _parent, _accept) do {                      \
    ctr_wcomp_t *_wcomp = CTR_WCOMP_CAST(_wc);                          \
    _wcomp->this = (_wc);                                               \
    _wcomp->parent = (_parent);                                         \
    _wcomp->prev = NULL;                                                \
    _wcomp->next = NULL;                                                \
    _wcomp->accept = (_accept);                                         \
} while(0)

#define CTR_ACCEPT_NAME(_type)  (ctr_##_type##_accept)

#define CTR_ACCEPT_DEF(_type)                                           \
    static apr_status_t ctr_##_type##_accept(                           \
        ctr_wcomp_t *obj, const ctr_wcomp_visitor_t *vt, void *udata)   \
    {                                                                   \
        return vt->CTR_VISITOR_MEMBER_NAME(_type)(CTR_WCOMP_THIS(obj),  \
                                                  vt, udata);           \
    }

CTR_ACCEPT_DEF(block)
CTR_ACCEPT_DEF(form)
CTR_ACCEPT_DEF(heading)
CTR_ACCEPT_DEF(list)
CTR_ACCEPT_DEF(listitem)
CTR_ACCEPT_DEF(deflist)
CTR_ACCEPT_DEF(defterm)
CTR_ACCEPT_DEF(defdesc)
CTR_ACCEPT_DEF(deco)
CTR_ACCEPT_DEF(anchor)
CTR_ACCEPT_DEF(select)
CTR_ACCEPT_DEF(c3if)
CTR_ACCEPT_DEF(hrline)
CTR_ACCEPT_DEF(newline)
CTR_ACCEPT_DEF(image)
CTR_ACCEPT_DEF(editbox)
CTR_ACCEPT_DEF(passwd)
CTR_ACCEPT_DEF(radio)
CTR_ACCEPT_DEF(chkbox)
CTR_ACCEPT_DEF(hidden)
CTR_ACCEPT_DEF(submit)
CTR_ACCEPT_DEF(reset)
CTR_ACCEPT_DEF(option)
CTR_ACCEPT_DEF(textarea)
CTR_ACCEPT_DEF(text)
CTR_ACCEPT_DEF(emoji)
CTR_ACCEPT_DEF(rawtext)
CTR_ACCEPT_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(page) *page = apr_palloc(pool, sizeof(*page));
    CTR_WCONTAINER_INIT(page, NULL, pool);
    page->title = title;
    page->bgcolor = bgcolor;
    page->txtcolor = txtcolor;
    page->txtcolor2 = txtcolor2;
    page->lnkcolor = lnkcolor;
    return page;
}

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(block) *blk = apr_palloc(cont->pool, sizeof(*blk));
    CTR_WCOMP_INIT(blk, cont, CTR_ACCEPT_NAME(block));
    CTR_WCONTAINER_INIT(blk, cont, cont->pool);
    blk->align = align;
    blk->marquee = marquee;
    blk->mqedirect = mqedirect;
    blk->mqebehav = mqebehav;
    blk->mqeloop = mqeloop;
    return blk;
}

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(form) *frm = apr_palloc(cont->pool, sizeof(*frm));
    CTR_WCOMP_INIT(frm, cont, CTR_ACCEPT_NAME(form));
    CTR_WCONTAINER_INIT(frm, cont, cont->pool);
    frm->act = act;
    frm->mtd = mtd;
    frm->utn = utn;
    frm->align = align;
    frm->rdohash = apr_hash_make(cont->pool);
    return frm;
}

CTR_CLASS_NAME(heading) *ctr_heading_new(ctr_wcontainer_t *cont, int type,
                                         ctr_halign_t align)
{
    CTR_CLASS_NAME(heading) *hdg = apr_palloc(cont->pool, sizeof(*hdg));
    CTR_WCOMP_INIT(hdg, cont, CTR_ACCEPT_NAME(heading));
    CTR_WCONTAINER_INIT(hdg, cont, cont->pool);
    hdg->type = type;
    hdg->align = align;
    return hdg;
}

CTR_CLASS_NAME(list) *ctr_list_new(ctr_wcontainer_t *cont, int ordered)
{
    CTR_CLASS_NAME(list) *lst = apr_palloc(cont->pool, sizeof(*lst));
    CTR_WCOMP_INIT(lst, cont, CTR_ACCEPT_NAME(list));
    CTR_WCONTAINER_INIT(lst, cont, cont->pool);
    lst->ordered = ordered;
    return lst;
}

CTR_CLASS_NAME(listitem) *ctr_listitem_new(ctr_wcontainer_t *cont)
{
    CTR_CLASS_NAME(listitem) *li = apr_palloc(cont->pool, sizeof(*li));
    CTR_WCOMP_INIT(li, cont, CTR_ACCEPT_NAME(listitem));
    CTR_WCONTAINER_INIT(li, cont, cont->pool);
    return li;
}

CTR_CLASS_NAME(deflist) *ctr_deflist_new(ctr_wcontainer_t *cont)
{
    CTR_CLASS_NAME(deflist) *dlt = apr_palloc(cont->pool, sizeof(*dlt));
    CTR_WCOMP_INIT(dlt, cont, CTR_ACCEPT_NAME(deflist));
    CTR_WCONTAINER_INIT(dlt, cont, cont->pool);
    return dlt;
}

CTR_CLASS_NAME(defterm) *ctr_defterm_new(ctr_wcontainer_t *cont)
{
    CTR_CLASS_NAME(defterm) *dtm = apr_palloc(cont->pool, sizeof(*dtm));
    CTR_WCOMP_INIT(dtm, cont, CTR_ACCEPT_NAME(defterm));
    CTR_WCONTAINER_INIT(dtm, cont, cont->pool);
    return dtm;
}

CTR_CLASS_NAME(defdesc) *ctr_defdesc_new(ctr_wcontainer_t *cont)
{
    CTR_CLASS_NAME(defdesc) *ddc = apr_palloc(cont->pool, sizeof(*ddc));
    CTR_WCOMP_INIT(ddc, cont, CTR_ACCEPT_NAME(defdesc));
    CTR_WCONTAINER_INIT(ddc, cont, cont->pool);
    return ddc;
}

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(deco) *dec = apr_palloc(cont->pool, sizeof(*dec));
    CTR_WCOMP_INIT(dec, cont, CTR_ACCEPT_NAME(deco));
    CTR_WCONTAINER_INIT(dec, cont, cont->pool);
    dec->txtcolor = txtcolor;
    dec->txtcolor2 = txtcolor2;
    dec->bgcolor = bgcolor;
    dec->fsize = fsize;
    dec->blink = blink;
    return dec;
}

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(anchor) *anc = apr_palloc(cont->pool, sizeof(*anc));
    CTR_WCOMP_INIT(anc, cont, CTR_ACCEPT_NAME(anchor));
    CTR_WCONTAINER_INIT(anc, cont, cont->pool);
    anc->href = href;
    anc->akey = akey;
    anc->utn = utn;
    return anc;
}

CTR_CLASS_NAME(select) *ctr_select_new(ctr_wcontainer_t *cont,
                                       const char *name)
{
    CTR_CLASS_NAME(select) *sel = apr_palloc(cont->pool, sizeof(*sel));
    CTR_WCOMP_INIT(sel, cont, CTR_ACCEPT_NAME(select));
    CTR_WCONTAINER_INIT(sel, cont, cont->pool);
    sel->name = name;
    return sel;
}

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(c3if) *c3if = apr_palloc(cont->pool, sizeof(*c3if));
    CTR_WCOMP_INIT(c3if, cont, CTR_ACCEPT_NAME(c3if));
    CTR_WCONTAINER_INIT(c3if, cont, cont->pool);
    c3if->lang = lang;
    c3if->carrier = carrier;
    c3if->names = names;
    c3if->groups = groups;
    c3if->isfoma = isfoma;
    c3if->istuka = istuka;
    c3if->isxml = isxml;
    c3if->not = not;
    return c3if;
}

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(hrline) *hr = apr_palloc(cont->pool, sizeof(*hr));
    CTR_WCOMP_INIT(hr, cont, CTR_ACCEPT_NAME(hrline));
    hr->align = align;
    hr->size = size;
    hr->width = width;
    hr->color = color;
    return hr;
}

CTR_CLASS_NAME(newline) *ctr_newline_new(ctr_wcontainer_t *cont)
{
    CTR_CLASS_NAME(newline) *nl = apr_palloc(cont->pool, sizeof(*nl));
    CTR_WCOMP_INIT(nl, cont, CTR_ACCEPT_NAME(newline));
    return nl;
}

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(image) *img = apr_palloc(cont->pool, sizeof(*img));
    CTR_WCOMP_INIT(img, cont, CTR_ACCEPT_NAME(image));
    img->src = src;
    img->alt = alt;
    img->cvmode = cvmode;
    img->percent = percent;
    img->copy = copy;
    img->mframe = mframe;
    return img;
}

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(editbox) *ebox = apr_palloc(cont->pool, sizeof(*ebox));
    CTR_WCOMP_INIT(ebox, cont, CTR_ACCEPT_NAME(editbox));
    ebox->name = name;
    ebox->val = val;
    ebox->size = size;
    ebox->max = max;
    ebox->style = style;
    return ebox;
}

CTR_CLASS_NAME(passwd) *ctr_passwd_new(ctr_wcontainer_t *cont,
                                       const char *name, const char *val,
                                       int size, int max)
{
    CTR_CLASS_NAME(passwd) *pwd = apr_palloc(cont->pool, sizeof(*pwd));
    CTR_WCOMP_INIT(pwd, cont, CTR_ACCEPT_NAME(passwd));
    pwd->name = name;
    pwd->val = val;
    pwd->size = size;
    pwd->max = max;
    return pwd;
}

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(radio) *rdo = apr_palloc(cont->pool, sizeof(*rdo));
    CTR_WCOMP_INIT(rdo, cont, CTR_ACCEPT_NAME(radio));
    rdo->name = name;
    rdo->val = val;
    rdo->chk = chk;
    rdo->rinfo = rinfo;
    rdo->no = no;
    return rdo;
}

CTR_CLASS_NAME(chkbox) *ctr_chkbox_new(ctr_wcontainer_t *cont,
                                       const char *name, const char *val,
                                       int chk)
{
    CTR_CLASS_NAME(chkbox) *cbox = apr_palloc(cont->pool, sizeof(*cbox));
    CTR_WCOMP_INIT(cbox, cont, CTR_ACCEPT_NAME(chkbox));
    cbox->name = name;
    cbox->val = val;
    cbox->chk = chk;
    return cbox;
}

CTR_CLASS_NAME(hidden) *ctr_hidden_new(ctr_wcontainer_t *cont,
                                       const char *name, const char *val)
{
    CTR_CLASS_NAME(hidden) *hdn = apr_palloc(cont->pool, sizeof(*hdn));
    CTR_WCOMP_INIT(hdn, cont, CTR_ACCEPT_NAME(hidden));
    hdn->name = name;
    hdn->val = val;
    return hdn;
}

CTR_CLASS_NAME(submit) *ctr_submit_new(ctr_wcontainer_t *cont,
                                       const char *name, const char *val)
{
    CTR_CLASS_NAME(submit) *smt = apr_palloc(cont->pool, sizeof(*smt));
    CTR_WCOMP_INIT(smt, cont, CTR_ACCEPT_NAME(submit));
    smt->name = name;
    smt->val = val;
    return smt;
}

CTR_CLASS_NAME(reset) *ctr_reset_new(ctr_wcontainer_t *cont, const char *name,
                                     const char *val)
{
    CTR_CLASS_NAME(reset) *rst = apr_palloc(cont->pool, sizeof(*rst));
    CTR_WCOMP_INIT(rst, cont, CTR_ACCEPT_NAME(reset));
    rst->name = name;
    rst->val = val;
    return rst;
}

CTR_CLASS_NAME(option) *ctr_option_new(ctr_wcontainer_t *cont,
                                       const char *val, int sel,
                                       const char *txt)
{
    CTR_CLASS_NAME(option) *opt = apr_palloc(cont->pool, sizeof(*opt));
    CTR_WCOMP_INIT(opt, cont, CTR_ACCEPT_NAME(option));
    opt->val = val;
    opt->sel = sel;
    opt->txt = txt;
    return opt;
}

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(textarea) *txa = apr_palloc(cont->pool, sizeof(*txa));
    CTR_WCOMP_INIT(txa, cont, CTR_ACCEPT_NAME(textarea));
    txa->name = name;
    txa->rows = rows;
    txa->cols = cols;
    txa->style = style;
    txa->txt = txt;
    return txa;
}

CTR_CLASS_NAME(text) *ctr_text_new(ctr_wcontainer_t *cont, const char *s)
{
    CTR_CLASS_NAME(text) *txt = apr_palloc(cont->pool, sizeof(*txt));
    CTR_WCOMP_INIT(txt, cont, CTR_ACCEPT_NAME(text));
    txt->txt = s;
    return txt;
}

CTR_CLASS_NAME(emoji) *ctr_emoji_new(ctr_wcontainer_t *cont, const char *id)
{
    CTR_CLASS_NAME(emoji) *emj = apr_palloc(cont->pool, sizeof(*emj));
    CTR_WCOMP_INIT(emj, cont, CTR_ACCEPT_NAME(emoji));
    emj->id = id;
    return emj;
}

CTR_CLASS_NAME(rawtext) *ctr_rawtext_new(ctr_wcontainer_t *cont,
                                         ctr_rawtype_t type, const char *s)
{
    CTR_CLASS_NAME(rawtext) *rtxt = apr_palloc(cont->pool, sizeof(*rtxt));
    CTR_WCOMP_INIT(rtxt, cont, CTR_ACCEPT_NAME(rawtext));
    rtxt->type = type;
    rtxt->txt = s;
    return rtxt;
}

CTR_CLASS_NAME(brank) *ctr_brank_new(ctr_wcontainer_t *cont)
{
    CTR_CLASS_NAME(brank) *brk = apr_palloc(cont->pool, sizeof(*brk));
    CTR_WCOMP_INIT(brk, cont, CTR_ACCEPT_NAME(brank));
    return brk;
}
