// The MIT License (MIT)
//
// Copyright (C) 2026 Scott Duensing
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#define DVX_WIDGET_IMPL
// widgetLabel.c  -- Label widget
//
// Static text display  -- the simplest widget. Not focusable, not interactive.
// Supports accelerator keys via '&' prefix: when the user presses Alt+key,
// focus moves to the next focusable widget after this label. This follows
// the Win3.1 convention where labels act as keyboard shortcuts for adjacent
// controls (e.g., a label "&Name:" before a text input).
//
// The widget owns its text string (strdup'd on set, freed on destroy).
// Callers can pass transient strings safely.
//
// Background is transparent by default (bgColor == 0 means use the parent's
// content background color from the color scheme). The +1 in calcMinH adds a
// pixel of breathing room below the text baseline.

#include "dvxWgtP.h"

static int32_t sTypeId = -1;

typedef struct {
    const char  *text;
    WidgetAlignE textAlign;
} LabelDataT;


// ============================================================
// Prototypes
// ============================================================

WidgetT *wgtLabel(WidgetT *parent, const char *text);
int32_t wgtLabelGetAlign(const WidgetT *w);
void wgtLabelSetAlign(WidgetT *w, WidgetAlignE align);
void wgtRegister(void);
void widgetLabelCalcMinSize(WidgetT *w, const BitmapFontT *font);
void widgetLabelPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors);


WidgetT *wgtLabel(WidgetT *parent, const char *text) {
    return widgetAllocWithText(parent, sTypeId, sizeof(LabelDataT), text);
}


int32_t wgtLabelGetAlign(const WidgetT *w) {
    if (w && w->type == sTypeId) {
        LabelDataT *d = (LabelDataT *)w->data;
        return (int32_t)d->textAlign;
    }

    return 0;
}


void wgtLabelSetAlign(WidgetT *w, WidgetAlignE align) {
    if (w && w->type == sTypeId) {
        LabelDataT *d = (LabelDataT *)w->data;
        d->textAlign = align;
    }
}


void widgetLabelCalcMinSize(WidgetT *w, const BitmapFontT *font) {
    LabelDataT *d = (LabelDataT *)w->data;
    w->calcMinW = textWidthAccel(font, d->text);
    w->calcMinH = font->charHeight + 1;
}


void widgetLabelPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors) {
    LabelDataT *ld = (LabelDataT *)w->data;
    int32_t textW   = textWidthAccel(font, ld->text);
    int32_t textX   = w->x;
    int32_t textY   = w->y + (w->h - font->charHeight) / 2;

    if (ld->textAlign == AlignCenterE) {
        textX = w->x + (w->w - textW) / 2;
    } else if (ld->textAlign == AlignEndE) {
        textX = w->x + w->w - textW;
    }

    uint32_t fg = w->fgColor ? w->fgColor : colors->contentFg;
    uint32_t bg = w->bgColor ? w->bgColor : colors->contentBg;

    drawWidgetTextAccel(d, ops, font, textX, textY, ld->text, fg, bg, false, w->enabled, colors);
}


// ============================================================
// DXE registration
// ============================================================


static const WidgetClassT sClassLabel = {
    .version = WGT_CLASS_VERSION,
    .flags   = WCLASS_FOCUS_FORWARD | WCLASS_HAS_TEXT,
    .handlers = {
        [WGT_METHOD_PAINT]         = (void *)widgetLabelPaint,
        [WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetLabelCalcMinSize,
        [WGT_METHOD_GET_TEXT]      = (void *)widgetTextGet,
        [WGT_METHOD_SET_TEXT]      = (void *)widgetTextSet,
    }
};

static const struct {
    WidgetT *(*create)(WidgetT *parent, const char *text);
    void     (*setAlign)(WidgetT *w, WidgetAlignE align);
} sApi = {
    .create   = wgtLabel,
    .setAlign = wgtLabelSetAlign
};

static const char *sAlignNames[] = { "Left", "Center", "Right", NULL };

static const WgtPropDescT sProps[] = {
    { "Alignment", WGT_IFACE_ENUM, (void *)wgtLabelGetAlign, (void *)wgtLabelSetAlign, sAlignNames }
};

static const WgtIfaceT sIface = {
    .basName      = "Label",
    .props        = sProps,
    .propCount    = 1,
    .methods      = NULL,
    .methodCount  = 0,
    .events       = NULL,
    .eventCount   = 0,
    .createSig    = WGT_CREATE_PARENT_TEXT,
    .defaultEvent = "Click"
};

void wgtRegister(void) {
    sTypeId = wgtRegisterClass(&sClassLabel);
    wgtRegisterApi("label", &sApi);
    wgtRegisterIface("label", &sIface);
}
